readlink
ожидает символическую ссылку, а затем отображает файл/дир, на который указывает символическая ссылка.
Не усложняйте чем это должно быть.
find /home/jason/gPodder/ -name '*.mp3' -exec cp {} /home/jason/gPodder/mp3/ \;
или, возможно,
find /home/jason/gPodder/ -type f -name '*.mp3' -exec cp {} /home/jason/gPodder/mp3/ \;
, чтобы рассматривать только обычные файлы.
Чтобы скопировать файл только в том случае, если в папке назначения уже нет файла с таким именем, некоторые реализации cp
поддерживают для этого параметр -n
, или вы можете использовать -i
со стандартным вводом, перенаправленным из /dev/null
(но будьте осторожны, они не работают, если целью является тип каталога) или сделайте что-то вроде:
find /home/jason/gPodder/ -type f -name '*.mp3' \
! -execdir test -e /home/jason/gPodder/mp3/{} \; \
-exec cp {} /home/jason/gPodder/mp3/ \;
-execdir
является расширением стандарта POSIX find
, но поддерживается многими современными реализациями find
. Он работает как -exec
, но выполняет команду с родительским каталогом найденного объекта в качестве рабочего каталога. Кроме того, {}
будет базовым именем найденной вещи (либо file.mp3
, либо ./file.mp3
в зависимости от реализации find
), а не полный путь к нему. См. man find
.
Ошибка связана с bash "somecommand"
. При вызове bash
таким образом, bash
ожидает, что somecommand
будет путем к файлу сценария, а не последовательностью команд оболочки, и не может найти сценарий с именем, которое вы ему даете.
Чтобы выполнить произвольную серию команд оболочки, вам нужно bash -c "somecommand"
.
Но в этом случае просто используйте -exec cp
, как указано выше, или как в ответе Stéphane Chazelas.
Другие указали на проблемы с цитированием и выполнением.
Я предлагаю вам не использовать find -exec, а вместо этого найти список файлов и передать этот список в xargs и cp. Использование опции print0 поможет вам обойти любые «забавные» символы в именах файлов и каталогов
, например.
find sourcepath -name \*.mp3 -print0 \
| xargs -0 cp -t destinationpath
Преимущество этого заключается в том, что xargs будет собирать несколько имен файлов вместе из find и одновременно передавать их в cp, поэтому каждый экземпляр cp может копировать 20 или 100 файлов, а не запускать 1 вызов cp для каждого файла. xargs позаботится о том, чтобы вставить достаточное количество имен файлов в командную строку cp.
Вы также можете добавить параметр -P n к xargs, и он запустит несколько процессов cp параллельно.
На том основании, что ваши файлы находятся в той же файловой системе, что и целевая папка mp3. Вы можете добавить -l к cp, и он жестко свяжет файлы с местом назначения, а не копирует их.
напр.
find sourcepath -name \*.mp3 -print0 \
| xargs -0 -P 5 \
cp -l -t destinationpath
Как @Kusalananda сказал , вам не хватает -c
, чтобы иметь возможность использовать встроенный -скрипт.
Но даже в этом случае никогда не встраивайте {}
в шелл-код, это может привести к уязвимости, связанной с внедрением произвольной команды (подумайте, например, о файле с именем '$(reboot)'.mp3
в вашем примере ). Вместо этого сделайте его аргументом встроенного скрипта (, предполагая, что вам здесь нужен встроенный скрипт, а cp
— это просто пример ).
find... -exec sh -c 'cp "$1" /home/jason/gPodder/mp3' sh {} \;
(вам также не нужно bash
только для этого. Ваш sh
подойдет так же ).
Или, что еще лучше, передать сразу несколько аргументов вcp
:
find... -exec sh -c 'cp "$@" /home/jason/gPodder/mp3' sh {} +
С помощью GNU cp
вы также можете это сделать:
find... -exec cp -t /home/jason/gPodder/mp3 {} +