Как определить название текущего рабочего файла в regex операции?

Если я пытаюсь выполнить regex операцию на файлах как так (пример):

$ mv *.ext *.new.ext

Это не работает.

Как я удостоверяюсь, чтобы, когда я обрабатываю в пакетном режиме, переименовали или выполнили операцию на нескольких файлах, что они сохраняют свое текущее имя (не расширение, просто имя)?

Примечание: Я не ищу что-то как rename управляйте, потому что это должно работать на все, не просто переименовав файлы.

Примечание 2: Хорошо, эти ответы хороши, и объясняет вещи мне, что я правильно не понял прежде.Спасибо!

Рассматриваемую команду, которую я пытаюсь использовать, называют firmtool, и используется в 3DS доморощенная сцена.

Это упаковывает .bin файлы в .firm файлы, и я хотел бы, чтобы это работало на всех .bin файлах в каталоге, упаковывая их при сохранении настоящего имени.

Вот синтаксис, в котором я нуждаюсь для firmtool команда:

firmtool build test.firm -n 0x23F00000 -e 0 -D arm9loaderhax.bin -A 0x23F00000 -C NDMA

где test.firm вывод и arm9loaderhax.bin вход.

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

3
задан 22 May 2017 в 09:33

2 ответа

Хм. Вы can't1, не универсально.

* подстановочный знак. Оболочка разворачивает его. Когда Вы вводите

*.ext

Оболочка разворачивает его до списка всех файлов соответствия, как:

1.ext 2.ext whatever.ext

Именно это передается команде в Вашем случае mv. Если mv получает больше чем два аргумента, последним должен быть каталог, таким образом,

mv *.ext *.new

сбои с *.new не каталог, потому что mv получает длинный список аргументов.

Сама оболочка не поддерживает regex, но Linux имеет много утилит, которые делают, как жемчуг переименовывают...

rename -n 's/(.*)\.ext/$1.new/' *

И удалите -n после тестирования для реального переименования...

Но можно получить переменные имена в переменной и использовать ее для цикличного выполнения по файлам...

for f in *.ext; do echo mv -v -- "$f" "${f/.ext/.new}"; done

и удалите echo после тестирования для завершения переименования... Можно использовать почти любую команду с for, не только mv. Вот немного отличающийся пример на основе Вашего вопроса:

for f in *.bin; do
  firmtool build "${f%.bin}.firm" -n 0x23F00000 -e 0 -D "$f" -A 0x23F00000 -C NDMA
done

В этом случае ${f%.bin} расширится до значения переменной f с суффиксом .bin неизолированный (если это имеет такой суффикс; иначе это расширяется до значения f).

См. руководство по Расширению Параметра Shell для других типов расширения.

1waits, чтобы быть доказанным неправильным

5
ответ дан 1 December 2019 в 15:22

Что происходит и почему делает сбой команды mv

Давайте на самом деле исследуем то, что происходит при использовании капота strace.

$ touch file{1,2}.ext
$ strace -e trace=execve mv *.ext *.new.ext            
execve("/bin/mv", ["mv", "file1.ext", "file2.ext", "*.new.ext"], [/* 80 vars */]) = 0
mv: target '*.new.ext' is not a directory
+++ exited with 1 +++

Поскольку Zanna объяснили в ее ответе *.ext будет расширен оболочкой до всех файлов в текущем рабочем каталоге тот конец в .ext строка. То, что Вы видите в том примере, является этим *.new.ext не расширен, точно потому что нет никакого файла, который соответствует такому шаблону, т.е. нет никакого файла foo.new.ext где угодно следовательно окружите передачи это непосредственно как аргумент.

mv управляйте в свою очередь рассматривает это как следующий синтаксис:

mv [OPTION]... SOURCE... DIRECTORY

Если бы у Вас на самом деле был существующий каталог в последнем аргументе, то это работало бы

$ mv *.ext test_dir

$ tree       
.
└── test_dir
    ├── file1.ext
    └── file2.ext

Что Вы на самом деле хотите сделать

Ваша исходная цель, насколько я понимаю, состоит в том, чтобы переименовать каждый *.ext файл в соответствующий файл с .new.ext окончание. Это может быть сделано или с, переименовывают, поскольку Zanna показывает, или через цикличное выполнение в оболочке:

$ for f in ./*.ext ; do mv "$f" "$(basename "$f")".new.ext; done                         

$ ls
file1.ext.new.ext  file2.ext.new.ext

Заметьте использование basename извлечь часть прежде .ext и использование ./*.ext. Используйте если ./* предназначен для предотвращения проблем с именами файлов, которые могут иметь продвижение - и обычно рекомендуется подход вместо пустого *

Дополнительные примечания

В Вашем вопросе Вы заявили:

Если я пытаюсь выполнить regex операцию на файлах

Это - часть проблемы. * в оболочке Расширение Пути, которое расширяется до списка файлов в текущем рабочем каталоге. Это не работает в том же смысле регулярного выражения abc.* где Вы строка совпадения, запускающаяся с abc с любым нулем последнего знака или больше раз.

Как я удостоверяюсь, чтобы, когда я обрабатываю в пакетном режиме, переименовали или выполнили операцию на нескольких файлах, что они сохраняют свое текущее имя (не расширение, просто имя)?

Можно выполнить итерации по списку файлов с помощью a for цикл, и активно извлекает использование имени файла basename команда, как я показал выше. prename может использоваться, если Вы правильно определяете замены в regex выражении. О чем хорошо prename это, это имеет функциональность пробного прогона ( -n переключатель), где никакое фактическое переименование не выполняется. Та же идея может использоваться с повторением, где Вы используете echo вместо mv сначала.

Я не ищу что-то как переименовать команда, потому что это должно работать на все, не просто переименовав файлы.

Снова, * насколько оболочка затронута соглашения с файлами в текущем каталоге. Это не то же как регулярные выражения. Ваш подход должен быть адаптирован согласно инструментам, которые Вы используете.

1
ответ дан 1 December 2019 в 15:22

Другие вопросы по тегам:

Похожие вопросы: