Задача
Измените эти имена файлов:
- F00001-0708-RG-биаслюйда
- F00001-0708-CS-akgdlaul
- F00001-0708-VF-hioulgigl
к этим именам файлов:
- F0001-0708-RG-биаслюйда
- F0001-0708-CS-akgdlaul
- F0001-0708-VF-hioulgigl
Код оболочки
Тестировать:
ls F00001-0708-*|sed 's/\(.\).\(.*\)/mv & \1\2/'
Для выполнения:
ls F00001-0708-*|sed 's/\(.\).\(.*\)/mv & \1\2/' | sh
Мой вопрос
Я не понимаю код sed. Я понимаю, что это за команда подстановки
$ sed 's/something/mv'
означает. И я немного понимаю регулярные выражения. Но я не понимаю, что здесь происходит:
\(.\).\(.*\)
или здесь:
& \1\2/
Первое, на мой взгляд, просто означает: «один символ, за которым следует один символ, за которым следует последовательность из одного символа любой длины» - но, безусловно, это еще не все. Что касается последней части:
& \1\2/
Я понятия не имею.
bash
shell
sed
file-rename
Дэниел Андервуд
источник
источник
Ответы:
Во-первых, я должен сказать, что самый простой способ сделать это - использовать команды prename или rename.
В Ubuntu, OSX (пакет Homebrew, пакет
rename
MacPortsp5-file-rename
) или других системах с переименованием Perl (предварительное имя):или в системах с переименованием из util-linux-ng, например RHEL:
Это намного понятнее, чем эквивалентная команда sed.
Но что касается понимания команды sed, вам может помочь справочная страница sed. Если вы запустите man sed и выполните поиск & (используя команду / для поиска), вы найдете это специальный символ в s / foo / bar / replacements.
s/regexp/replacement/ Attempt to match regexp against the pattern space. If success‐ ful, replace that portion matched with replacement. The replacement may contain the special character & to refer to that portion of the pattern space which matched, and the special escapes \1 through \9 to refer to the corresponding matching sub-expressions in the regexp.
Следовательно,
\(.\)
соответствует первому символу, на который может ссылаться\1
. Затем.
соответствует следующему символу, который всегда равен 0. Затем\(.*\)
соответствует остальной части имени файла, на которую можно ссылаться\2
.Строка замены объединяет все вместе, используя
&
(исходное имя файла),\1\2
которое является каждой частью имени файла, кроме 2-го символа, который был 0.Это довольно загадочный способ сделать это, ИМХО. Если по какой-то причине команда переименования была недоступна, и вы хотели использовать sed для переименования (или, возможно, вы делали что-то слишком сложное для переименования?), Более явное выражение в вашем регулярном выражении сделало бы его более читаемым. Возможно что-то вроде:
ls F00001-0708-*|sed 's/F0000\(.*\)/mv & F000\1/' | sh
Возможность увидеть, что на самом деле меняется в s / search / replace /, делает его более читаемым. Также он не будет высасывать символы из вашего имени файла, если вы случайно запустите его дважды или что-то в этом роде.
источник
rename
это сама «переименованная» ссылка. т.е.rename
был "переименован" изprename
... например, в Ubuntu:readlink -f $(which rename)
output/usr/bin/prename
...rename
Упомянутая Дэвидом программа совершенно другая.sh
? это потенциально опасно, поскольку может быть выполнен произвольный код (вы обрабатываете данные как код).у вас есть объяснение sed, теперь вы можете использовать только оболочку, внешние команды не нужны
for file in F0000* do echo mv "$file" "${file/#F0000/F000}" # ${file/#F0000/F000} means replace the pattern that starts at beginning of string done
источник
sed
Пару лет назад я написал небольшой пост с примерами пакетного переименования с использованием :http://www.guyrutenberg.com/2009/01/12/batch-renaming-using-sed/
Например:
for i in *; do mv "$i" "`echo $i | sed "s/regex/replace_text/"`"; done
Если регулярное выражение содержит группы (например
\(subregex\
), вы можете использовать их в тексте замены как\1\
и\2
т. Д.источник
Самый простой способ:
for i in F00001*; do mv "$i" "${i/F00001/F0001}"; done
или, портативно,
for i in F00001*; do mv "$i" "F0001${i#F00001}"; done
Это заменяет
F00001
префикс в именах файлов наF0001
. кредиты для mahesh здесь: http://www.debian-administration.org/articles/150источник
mv "$i" "${i/F00001/F0001}"
. Но +1sed
командаозначает заменить:
с участием:
как обычная
sed
команда. Однако скобки&
и\n
маркеры это немного меняют.Строка поиска соответствует (и запоминает как образец 1) одиночному символу в начале, за которым следует единственный символ, за которым следует остальная часть строки (запоминается как образец 2).
В строке замены вы можете ссылаться на эти совпадающие шаблоны, чтобы использовать их как часть замены. Вы также можете ссылаться на всю согласованную часть как
&
.Таким образом, эта
sed
команда создаетmv
команду на основе исходного файла (для источника) и символа 1 и 3 и далее, эффективно удаляя символ 2 (для пункта назначения). Это даст вам серию строк в следующем формате:и так далее.
источник
ls | sed "s/\(.\).\(.*\)/mv & \1\2/" | bash
ls
, пропуститьsed
и затем пропустить оболочку! он подлежит выполнению произвольного кода с поддельными именами файлов. Проблема в том, что данные следует рассматривать как данные, и здесь они обычно сериализуются в код без каких-либо мер предосторожности. Я бы хотел, чтобы paxdiablo удалил этот ответ, поскольку он действительно не показывает хорошей практики. (Я наткнулся на этот вопрос, потому что новичок случайно набрал| sh
команду, которая не сработала, и, увидев этот вопрос и ответы, подумал, что это будет работать лучше - я в ужасе!):)
.Символ обратной косой черты с пареной означает: «при сопоставлении с шаблоном сохраняйте то, что соответствует здесь». Позже, на стороне замещающего текста, вы можете вернуть эти запомненные фрагменты с помощью «\ 1» (первый блок в скобках), «\ 2» (второй блок) и т. Д.
источник
Если все, что вы действительно делаете, это удаление второго символа, независимо от того, что это такое, вы можете сделать это:
но ваша команда создает
mv
команду и передает ее оболочке для выполнения.Это не более читабельно, чем ваша версия:
find -type f | sed -n 'h;s/.//4;x;s/^/mv /;G;s/\n/ /g;p' | sh
Четвертый символ удален, потому что
find
перед каждым именем файла добавляется "./".источник
| sh
команду, которая не работает, в надежде, что она сработает. лучше. Это ужасно! (и, кроме того, это не очень хорошая практика). Надеюсь, ты поймешь!В круглых скобках указаны конкретные строки для использования с числами с обратной косой чертой.
источник
ls F00001-0708-*|sed 's|^F0000\(.*\)|mv & F000\1|' | bash
источник
Вот что бы я сделал:
for file in *.[Jj][Pp][Gg] ;do echo mv -vi \"$file\" `jhead $file| grep Date| cut -b 16-| sed -e 's/:/-/g' -e 's/ /_/g' -e 's/$/.jpg/g'` ; done
Затем, если все в порядке, добавьте
| sh
в конец. Так:for file in *.[Jj][Pp][Gg] ;do echo mv -vi \"$file\" `jhead $file| grep Date| cut -b 16-| sed -e 's/:/-/g' -e 's/ /_/g' -e 's/$/.jpg/g'` ; done | sh
источник
Используя переименование perl ( обязательно в панели инструментов):
rename -n 's/0000/000/' F0000*
Удалите
-n
переключатель, когда выход выглядит хорошо, чтобы переименовать по-настоящему.Существуют и другие инструменты с таким же названием, которые могут или не могут делать это, поэтому будьте осторожны.
Команда переименования, входящая в
util-linux
пакет, не работает.Если вы запустите следующую команду (
GNU
)и понимаете
perlexpr
, значит, это правильный инструмент.Если нет, сделать его по умолчанию (обычно уже так)
Debian
и производным, напримерUbuntu
:$ sudo apt install rename $ sudo update-alternatives --set rename /usr/bin/file-rename
Для Archlinux:
Для дистрибутивов семейства RedHat:
Пакет 'prename' находится в репозитории EPEL .
Для Gentoo:
Для * BSD:
или
p5-File-Rename
Для пользователей Mac:
Если у вас нет этой команды с другим дистрибутивом, найдите свой менеджер пакетов, чтобы установить ее, или сделайте это вручную :
Старая автономная версия может быть найдена здесь
человек переименовать
Этот инструмент был изначально написан Ларри Уоллом, отцом Perl.
источник
for i in *; do mv $i $(echo $i|sed 's/AAA/BBB/'); done
источник