log_<date>.txt
ネストされたディレクトリに散在している同じ命名法を共有するファイルがありますroot
。<date>
ファイルがYYYYmmddHHMM形式で生成された日付はどこにありますか?コード互換性の問題のため、すべてのファイルの名前を次のように変更したいと思います。<date>_log.txt
式をキャプチャする必要があることを知っていますが、<date>
Bashではどうすればよいですか?また、入れ子になったディレクトリでこれをどのように実行しますか?
ベストアンサー1
シェル変数にこれらのファイルの1つの名前があるとしますname
。log_
次に、完了を使用して変数値から対応するビットを削除し、完了を使用して${name#log_}
ビット.txt
を削除します${name%.txt}
。残りは日付であり、その形式は本質的に興味深いものではありません。削除された値を取得し、_log_.txt
最後に追加して新しい名前を作成するのは簡単です。
単一のディレクトリにあるファイルに対してこれを行うには、ループを使用します。変数値の先頭にあるディレクトリ名も削除する必要があります。
shopt -s nullglob
for name in root/log_*.txt; do
newname=root/${name#root/log_} # remove prefix, add root/ back
newname=${newname%.txt}_log.txt # remove suffix, add _log.txt back
printf 'Would move "%s" to "%s"\n' "$name" "$newname"
# mv -i "$name" "$newname"
done
mv
安全のため、実際のコマンドをコメントアウトしました。まず、何が起こるかを確認するには、一度テストを実行する必要があります。
シェルオプションはシェルを作成しnullglob
ます。bash
削除する拡張されていないままにするのではなく、一致しないパターン。これはlog_*.txt
、指定されたディレクトリにファイルがないとループがまったく実行されないことを意味します。
これは、現在のディレクトリを含むすべてのファイルに再帰的に適用できます。ややループのパターンを修正してください。
shopt -s globstar nullglob
for name in ./**/log_*.txt; do
dirpath=${name%/*} # get path of directory
newname=$dirpath/${name#$dirpath/log_} # remove prefix, add directory path back
newname=${newname%.txt}_log.txt # remove suffix, add _log.txt back
printf 'Would move "%s" to "%s"\n' "$name" "$newname"
# mv -i "$name" "$newname"
done
他の変更には、サブディレクトリを一致させることができるglobstar
シェルオプションの有効化が含まれます**
。また、新しい名前の前に追加できるようにディレクトリパスを選択しました。
find
ループへの入力を生成するためにも使用できます。
find . -type f -name 'log_*.txt' -exec sh -c '
for name do
dirpath=${name%/*} # get path of directory
newname=$dirpath/${name#$dirpath/log_} # remove prefix, add directory path back
newname=${newname%.txt}_log.txt # remove suffix, add _log.txt back
printf "Would move \"%s\" to \"%s\"\n" "$name" "$newname"
# mv -i "$name" "$newname"
done' sh {} +
これは、現在のディレクトリまたは次のディレクトリで名前が一致するすべての一般ファイルを検索し、デフォルトで上記の2番目のバリエーションのループと同じ操作を実行するlog_*.txt
インラインスクリプトに一括渡します。sh -c