次のスキーマに名前が付けられた数百または数千のファイルを含むフォルダがあるとします。
<random number of variable length>_<date code in YYYYMMDD format>.jpg
例:
73923_20180927.jpg
4457582_20180927.jpg
...
18733557_20190401.jpg
23573_20190401.jpg
...
bashスクリプトが実行すると期待するのは、これらの日付コードのリストを印刷することです。
20180927
20190401
...
これは簡単な作業のように聞こえますが、実際には簡単な作業です。スキーマは常に同じなので、ファイル名の必要な部分だけを印刷するために文字列操作を適用する方法を実装しました。しかし、各日付を一度だけ印刷する方法をまだ探しています。
この問題を解決する賢い方法はありますか?
ベストアンサー1
ファイル名がすべてパターンと一致すると仮定します./*_*.jpg
。
for name in ./*_*.jpg; do
name=${name##*_} # 4457582_20180927.jpg --> 20180927.jpg
printf '%s\n' "${name%.jpg}" # 20180927.jpg --> 20180927
done | sort -u
これはすべての名前で繰り返されます。名前ごとに一致する最長のプレフィックス文字列を削除します*_
。次に、サフィックスが削除された残りの文字列を出力します.jpg
。
その後、すべての文字列は最後に一意の文字列のリストのみを出力するようにソートされます。
ディレクトリが空になる危険性がある場合は、nullglob
ループ()のshopt -s nullglob
前にシェルオプションを設定する必要があります。これにより、展開されていないglobbingパターンを使用して一度実行されるのではなく、ループはまったく実行されません$name
。
特別な理由なく次のようにしますsort
。
declare -A skip=()
for name in ./*_*.jpg; do
key=${name##*_} # 4457582_20180927.jpg --> 20180927.jpg
key=${key%.jpg} # 20180927.jpg --> 20180927
if [[ ! -v skip[$key] ]]; then
printf '%s\n' "$key"
skip[$key]=1
fi
done
ここでは、連想配列のキーとして出力された文字列を追跡しますskip
。文字列が配列のキーに対応する場合、文字列は出力されません。