ファイル名に生年月日を含む写真が数千枚あります。各出生年ごとに少なくとも100個のファイルを見つけてコピーする必要があります。たとえば、2000年生まれのための100ファイル、2001年生まれのための100ファイル...などがあります。
ファイル名の形式は次のとおりです。
35077502_1995-02-01_2012.jpg
この写真は2012年に撮影されたと推定されています。
bashスクリプトを使用して実行できますか?
ありがとう
ベストアンサー1
#!/bin/bash
IFS=$'\n' years=( $(find . -maxdepth 1 -name '*.jpg' -print0 |
sed -zEn 's/^.*_([0-9][0-9][0-9][0-9])-.*\.jpg/\1/p' |
tr '\0' '\n' |
sort -u)
)
for year in "${years[@]}" ; do
mkdir -p "$year"
find . -iname "*_${year}-*.jpg" -size +1k -print0 |
head -z -n 100 |
xargs -0r cp -t "$year"
done
これは、現在のディレクトリのファイル名から抽出された一意の4桁の年のセットを含む配列($years
)を構成します。ここで、年の前には下線(_
)があり、その後にはダッシュ(-
)が続きます。これにはsed
akaオプションのGNUバージョンが必要です。-z
--null-data
各年に対して最初にその年のディレクトリを作成し(ディレクトリがまだ存在しない場合)、それを使用してfind
必要なパターンと一致し、1 KBを超えるすべてのファイル名を一覧表示します。次に、そのリストから最初の100行をインポートし、head
ファイルxargs
を適切なディレクトリにコピーします。
ファイル名のリストは、すべての有効なファイル名に対して機能するようにパイプ全体でNULで終了します(つまり、ファイル名にスペース、タブ、改行文字、または他の珍しいが完全に有効な文字が含まれていても中断されません)。
これも必要ですGNUバージョンhead
-z
(これはLinuxの標準です。)オプション( --zero-terminated
NUL終了入力とも呼ばれます)を使用するためです。特にバージョンが必要です。2016年1月13日更新。また、cp
ターゲットディレクトリが最後の引数ではなく最初の引数になることを可能にするGNU(別名)オプションも必要です。-t
--target-directory
ファイルをソートする必要がある場合とsort -z
コマンドの間に挿入できます。たとえば、GNUバージョンの 。find
head
find ... -print0 | sort -z ... | head -z ...
sort
これは、あなたの質問のリビジョンに示されているように、ファイル名にアンダースコアがあり、.jpg
拡張子の前の最後の項目に年が続くと仮定します。
-iname "*${year}*.jpg"
年がファイル名のどこにでも表示される場合(下線なし、および間に秒を挿入)を使用できますが、*
最初の8桁は部分文字列を含むファイルの数に似ていることに注意してください。${year}
.jpg
60420017
2001
また、すべてのファイルに、、、、などの代わりに(大文字と小文字を区別しない)拡張子があると仮定します.jpg
。複数のファイル拡張子が必要な場合は、代わりにこのオプションを使用できます。.jpeg
.jpe
.jfif
.gif
.png
-iregex
-iname