次のような形式のファイルを含むフォルダを含むフォルダがあります
resultstatsDF_iris_2017-05-26--21-33-35-437096_methodnr-2_percentage-0.05_seed-0.wcr
それぞれの日付と時刻を削除したいので、この場合は
resultstatsDF_iris_methodnr-2_percentage-0.05_seed-0.wcr
これをbashで実行するにはどうすればよいですか?
答え1
本当にやりたいなら「bash で」、 それから
find . -name '*.wcr' -execdir bash -c '
shopt -s extglob; for f; do echo mv -- "$f" "${f/_+([0-9-])_/_}"; done
' bash {} +
+([0-9-])
これは、セット内の文字の1つ以上の出現に一致する拡張グロブに依存します。[0-9-]
${f/_2017+([0-9-])_/_}
たとえば、数字とダッシュを単純に一致させるだけでは一般的すぎる場合など、置換をより具体的に行うことができます。
注: 削除する echo
それが望みどおりに機能していることが確実になったら。
答え2
find
+を使用するprename
(Perl 名前変更) コマンド:
find yourfolder -type f -name "*.wcr" -exec prename 's/^(.+)_[0-9]{4}-[0-9]{2}-[0-9]{2}[^_]+(_.*)$/$1$2/' {} +
prename
アクションを追加せずに結果を表示するには-n
オプション(名前を変更するファイルの名前を印刷するが、名前を変更しない):
man rename
[0-9]{4}-[0-9]{2}-[0-9]{2}
- パターンは日付-類似部分文字列(例2017-05-26
)
答え3
使用方法perl 名前変更コマンド (どちらのバージョンでも、 util-linux は除くrename
):
find . -type f -name \*.wcr -exec rename 's/_\d{4}-(\d{2}-){2}-(\d{2}-){3}\d+_/_/' {} +
答え4
ファイルが常に 1 ディレクトリ レベルの深さにある場合は、 のようにして反復処理できますfor x in */*_20*_*
。どのパターンを使用するかは、名前を変更したくない他のファイルが存在するかどうかによって異なります。先ほど示したパターンでは、日付が で始まり、名前にとその後の別のアンデスコアが20
含まれるすべてのファイルの名前を変更する必要があることを前提としています。_20
シェルループを使用して名前の変更を行うことができます。パラメータ拡張新しいファイル名を構築するための構造。
for old_name in ./*/*_20_*_*; do
base=${old_name##*/} # remove the directory part
prefix=${base%%_20*} # remove everything from _20
suffix=${base#*_20} # remove everything up to _20
suffix=${suffix#*_} # ... then everything before the first remaining _
mv "$old_name" "${old_name%/*}/${prefix}_${suffix}"
done
ファイルの深さが異なる場合は、bash ≥4.3でshopt -s globstar
次のように実行できますfor x in **/*_20*_*; …
。パターン**
がオンになっている場合、任意のディレクトリの深さに一致しますglobstar
。これは、ディレクトリへのシンボリック リンクもトラバースするという注意点付きで、bash 4.0~4.2 でも機能します。これは、zsh と ksh でも機能しますが、注意点はありません。zsh ではそのまま使用でき、set -o globstar
ksh ではそのまま使用できます。