Как определить имя текущего рабочего файла в операции регулярного выражения?

Попробуйте nconvert

Как инструмент командной строки ИЛИ xnconvert как инструмент GUI

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

6 ответов

Хм. Вы не можете1, а не повсеместно.

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

*.ext

Оболочка расширяет ее до списка всех соответствующих файлов, таких как:

1.ext 2.ext whatever.ext

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

mv *.ext *.new

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

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

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 (если он имеет такой

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

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

5
ответ дан 22 May 2018 в 22:24
  • 1
    Хорошее объяснение :-) – Ravexina 21 May 2017 в 10:34
  • 2
    Этот процесс называется globbing , с globbing . – Bob 21 May 2017 в 11:40
  • 3
    @ Zanna Я хорошо, если он используется в структуре цикла, как в for f in ./*.ext . . ., как в моем ответе, тогда можно взять пик в текущем обработанном файле из расширения. Можно также использовать strace для просмотра того, что подстановочный знак * расширяется, но в противном случае вы правы - невозможно. Хороший ответ, + 1'd – Sergiy Kolodyazhnyy 21 May 2017 в 12:54
[D0] Хм. Вы не можете1, а не повсеместно.

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

*.ext

Оболочка расширяет ее до списка всех соответствующих файлов, таких как:

1.ext 2.ext whatever.ext

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

mv *.ext *.new

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

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

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 (если он имеет такой

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

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

5
ответ дан 18 July 2018 в 12:59
[D0] Хм. Вы не можете1, а не повсеместно.

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

*.ext

Оболочка расширяет ее до списка всех соответствующих файлов, таких как:

1.ext 2.ext whatever.ext

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

mv *.ext *.new

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

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

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 (если он имеет такой

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

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

5
ответ дан 24 July 2018 в 20:04

Что происходит и почему команда mv fail

Давайте посмотрим, что происходит под капотом, используя 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 +++

Как Занна объяснила в своем ответе *.ext будет расширяться оболочкой ко всем файлам в текущей рабочей директории, которые заканчиваются в строке .ext. То, что вы видите в этом примере, состоит в том, что *.new.ext не разворачивается, именно потому, что нет файла, который соответствует такому шаблону, т. Е. нет файла foo.new.ext в любом месте, поэтому оболочка передает это непосредственно как аргумент.

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

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

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

$ mv *.ext test_dir

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

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

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

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

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

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

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

В вашем вопросе вы said:

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

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

Если я пытаюсь запустить операцию регулярного выражения на files

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

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

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

1
ответ дан 22 May 2018 в 22:24

Что происходит и почему команда mv fail

Давайте посмотрим, что происходит под капотом, используя 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 +++

Как Занна объяснила в своем ответе *.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. Это можно сделать либо с помощью переименования, как показывает Занна, либо с помощью цикла в оболочке:

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

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

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

В вашем вопросе вы said:

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

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

Если я пытаюсь запустить операцию регулярного выражения на files

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

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

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

1
ответ дан 18 July 2018 в 12:59

Что происходит и почему команда mv fail

Давайте посмотрим, что происходит под капотом, используя 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 +++

Как Занна объяснила в своем ответе *.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. Это можно сделать либо с помощью переименования, как показывает Занна, либо с помощью цикла в оболочке:

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

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

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

В вашем вопросе вы said:

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

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

Если я пытаюсь запустить операцию регулярного выражения на files

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

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

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

1
ответ дан 24 July 2018 в 20:04

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

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