Использовать синтаксис bash-типа `$ {i% .mp3}` с xargs? - PullRequest
3 голосов
/ 08 октября 2010

Пример использования (надуманный!): Переименуйте файлы .mp3 в .txt.

Я хотел бы иметь возможность сделать что-то вроде

find -name '*.mp3' -print0 | xargs -0 -I'file' mv file ${file%.mp3}.txt

Это не работаеттак что я прибегнул к выводу find через sed -e 's/.mp3//g', что делает свое дело.

Хотя это выглядит немного хакерским; есть ли способ использовать обычный синтаксис bash ${x%y}?

Ответы [ 5 ]

2 голосов
/ 08 октября 2010

Нет, xargs -0 -I'file' mv file ${file%.mp3}.txt не будет работать, потому что переменная file будет расширяться программой xargs, а не оболочкой. На самом деле это не совсем правильно называть ее переменной, это называется "replace-str" в руководстве по xargs.

Обновление: чтобы просто использовать xargs и bash (а не sed или что-то подобное), вы, конечно, можете позволить xargs запустить процесс bash, который затем может выполнить любую замену:

find -name '*.mp3' -print0 | xargs -0 bash -c \
'while [ -n "$1" ]; do mv "$1" "${1%.mp3}.txt" ; shift; done;' "bash"
1 голос
/ 05 августа 2011

Просто чтобы добавить другое предложение, даже если оно не использует механизм подстановки оболочки, а вместо этого sed.

find -name '*.mp3' -print |
sed -e 's/\.mp3$//' -e "s/.*/mv '&\.mp3' '&\.txt'/" |
sh

Другими словами, создайте командную строку mv для каждого имени файлаи передайте результат в sh.

. Это не удастся, если в каком-либо из файлов есть апостроф (одинарная кавычка) в имени файла.Я в основном публикую это, чтобы противостоять синдрому «если все, что у вас есть, это xargs, то каждая проблема будет выглядеть как гвоздь».

Не у всех seds одинаковый синтаксис.В частности, я не уверен на 100%, что у вас может быть несколько аргументов -e на некоторых старых старых ОС SunOS (ищите XPG-совместимый sed в чем-то вроде /usr/ucb/blah/barf/vomit/xpg4/bin/sed)

1 голос
/ 09 октября 2010

Если у вас установлен GNU Parallel:

find -name '*.mp3' -print0 | parallel -0 mv {} {.}.txt

Если имена ваших файлов не содержат \ n (перевод строки), это тоже будет работать:

find -name '*.mp3' | parallel mv {} {.}.txt

Посмотрите вступительное видео, чтобы узнать больше о GNU Parallel http://www.youtube.com/watch?v=OpaiGYxkSuQ

0 голосов
/ 29 мая 2012
perl rename.pl 's/\.mp3$/.txt/' *.mp3  
# Or **/*.mp3 for zsh and bash with specific settings set, for a recursive 
# rename.

http://people.sc.fsu.edu/~jburkardt/pl_src/rename/rename.html

0 голосов
/ 08 октября 2010
find . -type f -name '*.mp3' | while read -r F
do
  mv "$F" "${F%.mp3}.txt"
done

Баш 4 +

shopt -s globstar
shopt -s nullglob
for file in **/*.mp3
do
    mv "$file" "${file%.mp3}.txt"
done
...