Используя sed для массового переименования файлов
цель
изменить эти имена:
- F00001-0708-RG-biasliuyda
- F00001-0708-CS-akgdlaul
- F00001-0708-VF-hioulgigl
к этим именам файлов:
- F0001-0708-RG-biasliuyda
- F0001-0708-CS-akgdlaul
- F0001-0708-VF-hioulgigl
Шелл-Кода
To тест:
ls F00001-0708-*|sed 's/(.).(.*)/mv & /'
выполнить:
ls F00001-0708-*|sed 's/(.).(.*)/mv & /' | sh
У Меня Вопрос
Я не понимаю код sed. Я понимаю, что такое подмена команда
$ sed 's/something/mv'
средства. И я понимаю регулярные выражения несколько. Но я не поймите, что здесь происходит:
(.).(.*)
или здесь:
& /
первый, для меня, просто выглядит так, как будто это означает: "один символ, затем следует один символ, а затем любая последовательность длины один характер" - но, конечно, есть больше, чем это. Насколько последняя часть:
& /
понятия не имею. Я действительно хочу понять этот код. Пожалуйста, помогите мне сюда, ребята.
10 ответов:
во-первых, я должен сказать, что самый простой способ сделать это-использовать команды prename или rename.
на Ubuntu, OSX (Homebrew package
rename
, пакет MacPortsp5-file-rename
), или другие системы с perl переименовать (prename):rename s/0000/000/ F0000*
или на системах с переименованием из util-linux-ng, таких как RHEL:
rename 0000 000 F0000*
это гораздо более понятно, чем эквивалентная команда 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 through to refer to the corresponding matching sub-expressions in the regexp.
таким образом,
\(.\)
соответствует первому символу, на который может ссылаться. Тогда
.
соответствует следующему символу, который всегда равен 0. Тогда\(.*\)
соответствует остальной части имени файла, на который может ссылаться.
строка замены объединяет все это с помощью
&
(оригинал именем) ичто все части имени кроме 2-го персонаж, который был 0.
это довольно загадочный способ сделать это, ИМХО. Если для по какой-то причине команда переименовать не была доступна, и вы хотели использовать sed, чтобы сделать переименование (или, возможно, вы делали что-то слишком сложное для переименования?), будучи более явным в вашем регулярном выражении, это сделает его намного более читабельный. Возможно, что-то вроде:
ls F00001-0708-*|sed 's/F0000\(.*\)/mv & F000/' | 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\
), то вы можете использовать их в тексте замены как\
,etc.
самый простой способ будет такой:
for i in F00001*; do mv "$i" "${i/F00001/F0001}"; done
или, портативно,
for i in F00001*; do mv "$i" "F0001${i#F00001}"; done
это заменяет
F00001
префикс в именахF0001
. кредиты махешу здесь:http://www.debian-administration.org/articles/150
The
sed
командаs/\(.\).\(.*\)/mv & /
средства на замену:
\(.\).\(.*\)
С:
mv &
обычный . Однако, в скобках,
&
и\n
маркеры немного меняют его.строка поиска соответствует (и запоминается как шаблон 1) одному символу в начале, за которым следует один символ, за которым следует остальная часть строки (запоминается как шаблон 2).
в Замена строка, вы можете ссылаться на эти совпадающие шаблоны, чтобы использовать их в качестве части замены. Вы также можете ссылаться на всю согласованную часть как
&
.так что
sed
команда делает создаетmv
команда на основе исходного файла (для источника) и символа 1 и 3 вперед, эффективно удаляя символ 2 (для назначения). Это даст вам ряд строк в следующем формате:mv F00001-0708-RG-biasliuyda F0001-0708-RG-biasliuyda mv abcdef acdef
и так далее.
обратная косая черта-paren означает: "сопоставляя шаблон, держитесь за материал, который соответствует здесь."Позже, на стороне замещающего текста, вы можете вернуть эти запомненные фрагменты с помощью "\1" (первый блок в скобках), "\2" (второй блок) и т. д.
если все, что вы действительно делаете, это удаление второго символа, независимо от того, что это такое, вы можете сделать это:
s/.//2
но ваша команда строит
mv
команда и передача ее в оболочку для выполнения.это не более читабельно, чем ваша версия:
find -type f | sed -n 'h;s/.//4;x;s/^/mv /;G;s/\n/ /g;p' | sh
четвертый символ удаляется, потому что
find
добавляет каждое имя файла с "./".
вот что я бы сделал:
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