Подтвердить что ты не робот

Использование 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

Код оболочки

Чтобы проверить:

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/

Я понятия не имею. Я действительно хочу понять этот код. пожалуйста, помогите мне здесь, ребята.

4b9b3361

Ответ 1

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

В Ubuntu, OSX (пакет Homebrew rename, пакет MacPorts p5-file-rename) или другие системы с perl rename (prename):

rename s/0000/000/ F0000*

или в системах с переименованием из util-linux-ng, таких как RHEL:

rename 0000 000 F0000*

Это намного понятнее, чем эквивалентная команда sed.

Но для понимания команды sed команда sed man помогает. Если вы запускаете man sed и выполняете поиск и (используя команду/для поиска), вы найдете его особым символом в s/foo/bar/replacement.

  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.

Сменная строка ставит все вместе, используя & (оригинал filename) и \1\2, который является каждой частью имени файла, за исключением второго символ, который был равен 0.

Это довольно загадочный способ сделать это, ИМХО. Если для по какой-то причине команда rename была недоступна, и вы хотели использовать sed сделать переименование (или, возможно, вы делали что-то слишком сложное для переименования?), более явное в вашем регулярном выражении сделало бы это более читаемым. Возможно, что-то вроде:

ls F00001-0708-*|sed 's/F0000\(.*\)/mv & F000\1/' | sh

Возможность увидеть, что на самом деле меняется в s/search/replacement/делает его более читаемым. Также он не будет высасывание символов из вашего имени файла, если вы случайно запустили его дважды или что-то в этом роде.

Ответ 2

у вас появилось ваше объяснение 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

Ответ 3

Самый простой способ:

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

Ответ 4

Я написал небольшую запись с примерами переименования пакетов с помощью 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 и т.д.

Ответ 5

Команда sed

s/\(.\).\(.*\)/mv & \1\2/

означает замену:

\(.\).\(.*\)

с:

mv & \1\2

как обычная команда sed. Однако скобки, метки & и \n немного меняют его.

Строка поиска соответствует (и запоминает как шаблон 1) одиночный символ в начале, за которым следует одиночный символ, оставленный остальной частью строки (запомнен как шаблон 2).

В строке замены вы можете ссылаться на эти сопоставленные шаблоны, чтобы использовать их как часть замены. Вы также можете ссылаться на всю согласованную часть как &.

Итак, что делает эта команда sed, это создание команды mv, основанной на исходном файле (для источника) и символе 1 и 3 и далее, эффективно удаляя символ 2 (для адресата). Он даст вам ряд строк в следующем формате:

mv F00001-0708-RG-biasliuyda F0001-0708-RG-biasliuyda
mv abcdef acdef

и т.д.

Ответ 6

Материал с обратной косой чертой означает, что "при совпадении с шаблоном держитесь за то, что соответствует здесь". Позже, на стороне замены текста, вы можете вернуть эти запомненные фрагменты с помощью "\ 1" (первый скобковый блок), "\ 2" (второй блок) и т.д.

Ответ 7

В скобках фиксируются определенные строки для использования с помощью обратных кодов.

Ответ 8

Если все, что вы действительно делаете, это удаление второго символа, независимо от того, что это такое, вы можете сделать это:

s/.//2

но ваша команда создает команду mv и передает ее в оболочку для выполнения.

Это не более читаемо, чем ваша версия:

find -type f | sed -n 'h;s/.//4;x;s/^/mv /;G;s/\n/ /g;p' | sh

Четвертый символ удаляется, потому что find добавляет каждое имя файла с помощью./".

Ответ 9

 ls F00001-0708-*|sed 's|^F0000\(.*\)|mv & F000\1|' | bash

Ответ 10

Вот что я буду делать:

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