У меня есть тысячи фотографий с указанием года рождения в имени файла. Мне нужно найти и скопировать не менее 100 файлов на каждый год рождения, скажем, 100 файлов на 2000 год рождения, 100 файлов на 2001 год, ... и так далее.
Вот формат имен файлов:
35077502_1995-02-01_2012.jpg
Думаю, 2012 год - год, когда была сделана фотография.
Можно ли это сделать с помощью сценария bash?
Спасибо
Если в именах файлов нет гадостей, то можно сделать
for year in 2000 2001; do
cp `ls *${year}*.jpg|head -n 100` destination
done
#!/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
Это создает массив ($years
), содержащий уникальный набор из 4 -цифр года, извлеченных из имен файлов в текущем каталоге, где году предшествует символ подчеркивания (_
), а за ним следует тире(-
). Для этого требуется версия GNU sed
для опции -z
, также известной как --null-data
.
Для каждого года сначала создается каталог для этого года, если он еще не существует, а затем используется find
для перечисления всех имен файлов, соответствующих требуемому шаблону, размер которых превышает 1 КБ. Затем этот список передается через head
для получения только первых 100 строк, а затем в xargs
для копирования файлов в соответствующий каталог.
Список имен файлов завершается NUL -на протяжении всего конвейера, поэтому он работает со всеми допустимыми именами файлов (, т. е. он не прерывается, если в именах файлов есть пробелы, символы табуляции, символы новой строки или другие необычные, но вполне допустимые символы.)
Для этого также требуется GNU-версия head
(, которая является стандартной для Linux ), потому что она использует опцию -z
(, также известную как--zero-terminated
)для ввода с завершением NUL -. В частности, для этого требуется версия более поздняя, чем 13 января 2016 года . Также требуется GNU cp
для параметра -t
(, также известного как --target-directory
), что позволяет указывать целевой каталог в качестве первого аргумента, а не последнего.
Если файлы необходимо отсортировать, то sort -z
можно вставить между командами find
и head
-, например. find... -print0 | sort -z... | head -z...
. Для этого также требуется версия GNU sort
.
Это предполагает, что, как указано в редакции вашего вопроса, имена файлов имеют знак подчеркивания, за которым следует год, как последний элемент перед расширением .jpg
.
Если год может появляться в любом месте имени файла, вам может понадобиться использовать-iname "*${year}*.jpg"
(без подчеркивания и с секундой *
между ${year}
и .jpg
), но следите за файлами, где восемь -цифровое число в начале похоже на 60420017
, которое содержит 2001
в качестве подстроки.
Это также предполагает, что все ваши файлы имеют (регистрозависимые -нечувствительные к регистру).jpg
расширения (, а не .jpeg
, .jpe
, .jfif
, .gif
, .png
и т. д. ). Если требуется несколько расширений имени файла, вместо -iname
можно использовать параметр -iregex
.