Используя 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 61

10 ответов:

во-первых, я должен сказать, что самый простой способ сделать это-использовать команды prename или rename.

на Ubuntu, OSX (Homebrew package rename, пакет MacPorts p5-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 добавляет каждое имя файла с "./".

 ls F00001-0708-*|sed 's|^F0000\(.*\)|mv & F000|' | 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