Пакетное переименование файлов в командной строке и Xargs
Итак, у меня есть следующая структура:
.
..
a.png
b.png
c.png
я запустил команду, чтобы изменить их размер
ls | xargs -I xx convert xx -resize xx.jpg
Теперь мой dir выглядит так
.
..
a.png.jpg
a.png
b.png.jpg
b.png
c.png.jpg
c.png
первый вопрос: как переименовать файл, чтобы у меня было только одно расширение. Не два. (в принципе, как я могу очистить свою первоначальную ошибку)?
Второй вопрос: в будущем, используя xargs, как изменить расширение файла simular на second command?
6 ответов
как переименовать файл, чтобы у меня было только одно расширение.
cd dir/with/messedup/files
for file in *.png.jpg; do
mv "$file" "${file%.png.jpg}.jpg"
done
в будущем, используя xargs, как изменить расширение файла simular на вторую команду?
насколько мне известно,это невозможно. Лучший способ сделать это - использовать for-loop с подстановкой параметров, как показано выше:
for file in *.png; do
convert "$file" -resize "${file%.png}.jpg"
done
если у вас есть файлы в подкаталогах, которые вы хотите преобразовать, затем вы можете трубить find
до while read
петли:
find . -type f -name '*.png' |
while read file; do
convert "$file" -resize "${file%.png}.jpg"
done
Примечание: это вообще считается плохая идея использовать выход ls
в shell-скрипт. Хотя ваш пример мог бы работать нормально, есть много примеров, где это не так. Например, если в ваших именах файлов появились новые строки (что позволяет unix), ls
вероятно, не избежать для тебя. (Это на самом деле зависит от вашей реализации, которая еще одна причина не использовать ls
в скриптах; это поведение сильно варьируется от одного окна к другому.) Вы получите более последовательные результаты, если вы используете find
во время чтения или цикла подстановки файлов (например,*.png
) в цикле for.
Это также можно сделать с xargs
и sed
изменить расширение файла.
ls | grep \.png$ | sed 'p;s/\.png/\.jpg/' | xargs -n2 mv
вы можете распечатать исходное имя файла вместе с тем, что вы хотите, чтобы имя файла. Затем попросите xargs использовать эти два аргумента в команде move. Для однострочного я также добавил grep, чтобы отфильтровать что-либо не *.PNG-файл.
опаздывает на вечеринку, но вот как вы можете переименовывать файлы с помощью xargs. Скажем, у вас есть куча файлов с именем fileN.формат SVG.png, и вы хотите назвать их fileN.png, где N может быть рядом целых чисел:
ls *.svg.png | xargs basename -s .svg.png | xargs -I {} mv {}.svg.png {}.png
первый xargs использует basename для удаления обоих .svg и .png, чтобы получить просто filenameN
. Второй xargs получает это голое имя и использует замену для переименования файла.
чтобы очистить вашу ошибку, попробуйте rename
утилиты. Проверьте manpage для деталей.
в вашем случае, вы могли бы сделать rename '.png.jpg' '.jpg' ./*
если ваш текущий каталог устанавливается должным образом.
так как у вас есть convert
доступно, я предполагаю, что у вас есть mogrify
тоже (imagemagick
suite). Всякий раз, когда я хочу это сделать, я копирую файлы в другой каталог и использую . Обычно мне это нужно только для изменения размера, но если вы измените формат изображения,mogrify
будет обрабатывать имена файлов (создание новых файлов с правильными именами файлов).
вы бы использовали его как mogrify -format jpg -resize [size] ./*.png
. Я не уверен, что -resize
без аргументов геометрии должен делать. Это не документировано и не работает на моей машине.
как рассуждал Тим пот, я не думаю, что вы можете заставить xargs обрабатывать имена файлов и расширения отдельно.
Я опоздал на эту вечеринку примерно на 3 года, у меня просто была аналогичная проблема, которую я выяснил сам. У меня был список png-файлов, которые я преобразовал с помощью inkscape, потому что поддержка svg ImageMagick плохая.
Я первоначально преобразовал их, сделав:
find . -name "*.svg" -exec inkscape {} --export-png={}.png
что, конечно, привело к той же проблеме, что и выше.
file1.svg
file1.svg.png
file2.svg
file2.svg.png
file3.svg
file3.svg.png
file4.svg
file4.svg.png
Я хотел переименовать *.формат SVG.png to *.png, это то, что я поранился...
find . -name "*.svg.png" -print0 | sed 's/.svg.png//g' | xargs -0 -I namePrefix mv namePrefix.svg.png namePrefix.png
это три вещи:
- найти в этом каталоге файлы с именем *.формат SVG.png, - print0 печатает на стандартный вывод
- sed изменяет стандартный вывод, в основном swap .формат SVG.PNG с ничего, так что я хотел сделать: файл1/файл2/файл file3/файл file4
- xargs -0 чтобы получить данные из sed, - я ссылаюсь на имя файла без расширения, а затем MV оригинальное имя файла на новое имя файла. Слово namePrefix не является чем-то особенным, просто хотел сделать это четкий.
редактировать
теперь я понимаю, что это самый запутанный способ сделать это. Можно просто использовать команду rename.
rename 's/svg\.png/.png/' *
мое решение похоже на многие решения xarg и особенно похоже на Schleis.
разница здесь - полная манипуляция регулярным выражением со ссылками на совпадения и командами sed, которые правильно игнорируют файлы, которые не совпадают, поэтому вам не нужно предварительно фильтровать свой список.
это также безопасно для файлов с пробелами и оболочкой meta.
изменить в замене к любому пожеланному расширение.
ls |
sed -nE 's/Rick\.and\.Morty\.(S03E[0-9]{2})\..*(\.[a-z0-9]{3})/"&" "Rick and Morty "/;T;p' |
xargs -n 2 mv
объяснение
на -n
arg tell sed не печатать ничего по умолчанию,T
команда говорит пропустить до конца сценария, если предыдущий s
команда не сделала замену, печать шаблонов (только если s
команда матчи).
на &
в замене есть ссылка на содержимое исходного соответствия имени файла.
если заменить mv
in команда с bash -c 'echo "run($#) $@"' bash
тогда мы можем видеть количество раз mv
будет вызываться, а с параметром count и value:
$ ls |
sed -nE 's/Rick\.and\.Morty\.(S03E[0-9]{2})\..*(\.[a-z0-9]{3})/"&" "Rick and Morty "/;T;p' |
xargs -n 2 bash -c 'echo "run($#) $@"' bash
run(2) Rick.and.Morty.S03E02.720p.HDTV.x264-BATV.mkv Rick and Morty S03E02.mkv
run(2) Rick.and.Morty.S03E03.720p.HDTV.x264-BATV.mkv Rick and Morty S03E03.mkv
run(2) Rick.and.Morty.S03E04.720p.HDTV.x264-BATV.mkv Rick and Morty S03E04.mkv
run(2) Rick.and.Morty.S03E05.HDTV.x264-BATV[ettv].mkv Rick and Morty S03E05.mkv
run(2) Rick.and.Morty.S03E06.720p.HDTV.x264-BATV.mkv Rick and Morty S03E06.mkv
run(2) Rick.and.Morty.S03E06.HDTV.x264-BATV.mkv Rick and Morty S03E06.mkv
run(2) Rick.and.Morty.S03E07.720p.HDTV.x264-BATV[ettv].mkv Rick and Morty S03E07.mkv
run(2) Rick.and.Morty.S03E08.720p.HDTV.x264-BATV.mkv Rick and Morty S03E08.mkv
run(2) Rick.and.Morty.S03E09.720p.HDTV.x264-BATV.mkv Rick and Morty S03E09.mkv
run(2) Rick.and.Morty.S03E10.720p.HDTV.x264-BATV.mkv Rick and Morty S03E10.mkv