ファイル名に生年月日を含む写真が数千枚あります。各出生年ごとに少なくとも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
答え2
ファイル名に不快な内容がなければできます
for year in 2000 2001; do
cp `ls *${year}*.jpg|head -n 100` destination
done
答え3
そしてzsh
:
for y ({1995..2017}) (cp -- **/*_$y.jpg(.LK+1[1,100]) destination)
**/
: すべてのレベルのサブディレクトリ内でアルファベット順にソート.
:一般ファイルのみLK+1
:長さが1KiBを超えています。[1,100]
:最初の100個。
n
(ソート順によってコピーするファイルが決まるため、数値でソートするにはglob修飾子を追加する必要があります。)
または、年のリストをハードコーディングし、ディレクトリを複数回クロールしないでください。
typeset -A files n
for f (**/*_<->.jpg(.LK+1)) {
y=${${f##*_}%.*}
((++n[$y] > 100)) || files[$y]+=$f$'\0'
}
for y (${(k)files}) {
mkdir -p $y && cp -- ${(0)files[$y]} $y
}
(テストされていません)