ファイル名のすべての点を下線で置き換えます。

ファイル名のすべての点を下線で置き換えます。

ファイル名とディレクトリ名にドットを含むサブディレクトリを含むディレクトリがあります。

$ ls -R
.:
dir  file.with.dots

./dir:
subdir.with.dots

./dir/subdir.with.dots:
other.file

現在、フォルダとフォルダ自体findの名前を変更したくないので、これらすべてのファイルをキャプチャするのは本当に難しいです。...

私も方法を読んだ。拡張子を変更せずにファイル名の点を下線に変更します。しかし、主な問題はファイルを再帰的に選択することであるため、これには適していません。

find点をとに変更しようとしましたtr

find $(pwd) -depth -name '*.*'|while read f; do mv -iv "$f" '"'$(echo $f|tr '.' '_')'"' ; done

ただし、ファイルパスとファイル自体にドットの両方が含まれているとエラーが発生します。

すべての点の名前を変更して下線に変更するにはどうすればよいですか?

答え1

そしてzsh

autoload zmv
zmv '(**/)(*.*)' '$1${2//./_}'

それ以外の場合は、アクセス権がある場合bash(アクセスする予定ksh93)、いつでも次のことができます。zsh

find . -depth ! -name '.*' -name '*.*' -exec bash -c '
  for file do
    dir=${file%/*}
    base=${file##*/}
    mv -i -- "$file" "$dir/${base//./_}"
  done' sh {} +

(たとえあなたが行った完全性チェックを見逃すでしょうzmv)。

これは(意図的に)隠されたファイルの名前を変更しません。

要点は、リストを深く優先して処理し(デフォルトzmvで実行され、で-depth使用されるfind)、ファイルのデフォルト名のみを変更することです。

これにより、次のことができます。

mv -- a.b/c.d a.b/c_d

そしてそれから:

mv -- a.b a_b

また、zmv以外のソリューションの場合は、同じディレクトリにファイルとディレクトリがある場合はa.b幸せになります。a_bmv -- a.b a_ba.b 入力する a_b/。これを防ぐには、GNUシステムの場合、-Tこのオプションをmv


ご覧のとおり、ループwhile readを使用するために回答を編集してみました。

while read1行に1つのコマンドを実行する必要がある場合でも、通常ループは避けるべきです。 1つを使用したい場合は、正しく使用するのが難しく、ksh / bash / zshismsが必要です。

{
  find . -depth ! -name '.*' -name '*.*' -exec printf '%s\0' {} + |
    while IFS= read -rd '' file; do
      dir=${file%/*}
      base=${file##*/}
      mv -i -- "$file" "$dir/${base//./_}"
    done <&3 3<&-
} 3<&0

(あなたの発見がそれをサポートするならば、これを置き換えることができます-exec printf '%s\0' {} +)。-print0

以下を行う必要があります。

  • -print0/-exec printf '%s\0' {} +改行はファイル名で有効な文字なので、改行を区切り文字として使用できないためです。
  • だからあなたは必要です-d ''readNLの代わりにNULまで読んでください)
  • IFS=IFS(つまり、forからすべての空白文字を削除しread、それ以外の場合は入力レコードの末尾から空白文字を削除します)。
  • -rそれ以外の場合、readバックスラッシュはエスケープ文字として扱われます(フィールドとレコードの区切り文字として使用されます)。
  • ファイル記述子と踊るその小さな男これは、標準入力がパイプではなくmv端末(-iプロンプトへの応答用)になりたいからですfind

関連情報