質問: すべてのファイル名で空白をアンダースコアに置き換える方法は? 以下のスクリプトは、特定のフォルダにあるすべてのファイル名に「空白」ではなく「アンダースコア」を配置します。フォルダだけでなく、すべてのサブフォルダとそれに含まれるファイルの名前に「空白」ではなく「アンダースコア」を配置するシェルスクリプトを作成するのに問題があります。誰かがこれを行う方法について何かヒントがありますか?これが私のコードです:#!/bin/bash ls | while read -r file; do mv -v "$file" `echo $file | tr ' ' '_'` done
回答: 私のアプローチ:find . -depth -name "* *" -execdir bash -c 'pwd; for f in "$@"; do mv -nv "$f" "${f// /_}"; done' dummy {} + 読みやすさのための複数行バージョン:find . -depth -name "* *" -execdir \ bash -c ' pwd for f in "$@"; do mv -nv "$f" "${f// /_}" done ' dummy {} + 説明: find . -name "* *"は、名前を変更する必要があるオブジェクトを検索します。注findはそのテストで非常に柔軟であるため、たとえばディレクトリのみの名前を変更したい場合は、find . -depth -type d -name "* *"で始めます。 -execdirは、オブジェクトがあるディレクトリで指定されたプロセス(bash)を実行するため、{}によって渡されるパスは、./barではなく常に./foo/barのようになります。つまり、パス全体を気にする必要はありません。欠点は、mv -vでパスが表示されないため、情報のためにpwdを追加しました(必要に応じて省略できます)。 bashでは、"${baz// /_}"構文を使用できます。 -depthは、次のことが起こらないようにします。findは、ディレクトリの名前を変更し(該当する場合)、そのコンテンツをoldパスで処理しようとします。 {} +は、bashにmultipleオブジェクトをフィードできます({} \;構文とは異なります)。 for f in "$@"で繰り返します。新しいプロセスの作成にはコストがかかるため、すべてのオブジェクトに対して個別のbashプロセスを実行しないことがポイントです。個別のmv- sを実行することは簡単に避けられないと思います。それでも、bash呼び出しの数を減らすことは、良い最適化のようです(pwdはbashに組み込まれており、プロセスのコストはかかりません)。ただし、-execdir ... {} +は、異なるディレクトリのファイルを一緒に渡しません。 -exec ... {} +の代わりに-execdir ... {} +を使用することで、プロセスの数をさらに減らすことができますが、ファイル名だけでなくパスにも注意する必要があります( この他の回答 と比較してください)まともな仕事をするが while readはそれを遅くする )。これは、速度と(相対的な)単純さの問題です。 -execでの私の解決策は下にあります。 {}がdummy内で$0になる直前のbash。 "$@"は"$1" "$2" ...と同等であるため("$0" "$1" ...ではない)、このダミー引数が必要です。このようにして、{}によって渡されたすべてのものは後で"$@"として利用できます。 より複雑でわずかに最適化されたバージョン( 別の回答 から取得したさまざまな${...}トリック):find . -depth -name "* *" -exec \ bash -c ' for f in "$@"; do n="${f##*/}" mv -nv "$f" "${f%/*}/${n// /_}" done ' dummy {} + 別の(実験的!)アプローチには vidir が含まれます。秘訣はvidirが$editorを使用することですインタラクティブエディタではないかもしれません:find . -name "* *" | editor='sed -i s/\d32/_/g' vidir - 警告: これは、特殊文字(たとえば、改行)を含むファイル/ディレクトリ名に対して失敗します。 s/ /_/gを直接使用することはできません。\d32は回避策です。 vidirがどのように機能するかにより、数字またはタブを置き換えたい場合、アプローチはトリッキーになります。 ここで、vidirは、ファイル名(ベース名)だけでなくパスでも機能するため、ファイルのみ(つまり、ディレクトリではない)の名前を変更するのは難しい場合があります。 それにもかかわらず、あなたが何をしているのかを知っているなら、これは仕事をさらに速くするかもしれません。ただし、一般的なケースでは、vidirのこのような(絶対的な)使用はお勧めしません。この実験的アプローチが興味深いと感じたので、それを回答に含めました。