2013-11-16 4 views
1

Я новичок в Linux и bash-скриптах, и в настоящее время я в тупике с этой проблемой!Копирование уникальных файлов в новое место

У меня есть каталог, содержащий много изображений, из которых мне нужно скопировать уникальные изображения в новое место. Я знаю, что существует множество вариантов того, как это сделать, но на данный момент у меня очень ограниченные знания, поэтому я понимаю, что я ошибаюсь.

Я использовал find и cat для создания этого списка и попытался скопировать файлы с целью сравнить их (используя md5 и проверить имена файлов), когда они есть.

Однако текстовый файл содержит 30 файлов, но только 18 были скопированы. Может ли кто-нибудь посоветовать?

Мой код для поиска файлов является -

find $1 -name "IMG_****.JPG" | cat > list.txt 

и мой код, чтобы скопировать из списка

for image in $(cat list.txt); 
do 
cp $image $2 
done 
+1

У вас возникли ошибки? Это должно либо работать, либо отображать ошибки ... –

+0

Тематическое чтение: [ParsingLS] (http://mywiki.wooledge.org/ParsingLs) и [бесполезное использование кошки] (http://partmaps.org/era/unix/ award.html). – ghoti

+1

Кроме того, что именно вы подразумеваете под именем '' IMG _ ****. JPG? '? Это соответствует 'IMG_.JPG', а также' IMG_abcde123.JPG'. Это ваше намерение? Если да, просто используйте 'IMG _ *. JPG' для ясности. Если вы действительно хотите использовать только файлы с 4 символами между '_' и' .', используйте 'IMG _ ????. JPG'. Подробнее см. В [справочной странице] (http://www.gnu.org/software/bash/manual/bashref.html#index-pathname-expansion). – ghoti

ответ

5

Вы делаете это слишком сложно. Не перекачивайте find на cat, чтобы передать его в список. Это ненужное использование cat. Если вы должны, вы можете перенаправить вывод каждой программы непосредственно:

find "$1" -name "IMG_*.JPG" > list.txt 

Также do not use for to read lines from a file. Лучше use while with read:

while read -r filename; do 
    cp "$filename" "$2" 
done < list.txt 

Но это еще проще. Вы можете просто работать с файлами непосредственно из find:

find "$1" -name "IMG_*.JPG" -exec cp {} "$2" \; 

Здесь {} будет заменен каждого файла, что find находками. Не забывайте, что , так что пробелы в пути к файлам не проблема.

Еще более простой метод с параметрами Bash:

shopt -s nullglob globstar 
cp -t "$2" -- "$1"/**/IMG_*.JPG 

Здесь globstar позволяет рекурсивное согласование каталогов через **. Опция -t для cp определяет цель операции копирования. * Команда будет расширена до cp -t target -- source1/IMG_foo.JPG source2/IMG_bar.JPG и так далее.


Теперь, что касается вашей первоначальной проблемы, возможно, некоторые изображения имеют пространство в их имени. Это нарушит ваш оригинальный сценарий. Если ваши файлы изображений содержали новую строку в их имени, это также не сработало бы с while read … - но вы бы получили ошибку в этом случае, если файл не был найден.

Также обратите внимание, что cp перезаписывает файлы с тем же именем. Не запрашивая подтверждения. Поэтому, если в ваших подкаталогах есть изображения с одинаковым именем файла, вы получите только один результат с последней перезаписью существующего.

* -- не является абсолютно необходимым, но это хорошая привычка включать его, чтобы сообщить команду, когда аргументы параметров закончены.

+0

Спасибо за совет - я все еще понимаю возможности различных команд! – user2846121

+0

@ пользователь2846121 уверенный. Если проблема не в том, что изображения перезаписаны (потому что ваш файл содержит 30 строк и всего 18 копий), тогда это было бы странно, но на данный момент у меня нет другого объяснения. Возможно, вы можете показать нам вывод команды 'find', без части' exec'. – slhck

+0

@gniourf_gniourf Жизнеспособное предложение. Глобусы все еще полностью недооценены. Хотя я не знаю, имеет ли OP вложенные каталоги, поэтому '' $ 1 "/ **/IMG _ *. JPG' может быть в порядке с' shopt -s globstar'. – slhck

Смежные вопросы