2011-01-17 6 views
5

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

я сделал сценарий, который может рекурсивно переименовывать файлы [http://pastebin.com/raw.php?i= kXeHbDQw]:

например: перед:

THIS i.s my file (1).txt 

после выполнения сценария:

This-i-s-my-file-1.txt 

Ok. здесь:

Но: когда я хотел проверить его «полностью», с именами файлов, как это:

¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÂÃÄÅÆÇÈÊËÌÎÏÐÑÒÔÕ×ØÙUÛUÝÞßàâãäåæçèêëìîïðñòôõ÷øùûýþÿ.txt 
áíüűúöőóéÁÍÜŰÚÖŐÓÉ!"#$%&'()*+,:;<=>[email protected][\]^_`{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ¡¢£.txt 

он не [http://pastebin.com/raw.php?i=iu8Pwrnr ]:

$ sh renamer.sh directorythathasthefiles 
mv: cannot stat `./áíüűúöőóéÁÍÜŰÚÖŐÓÉ!"#$%&\'()*+,:;<=>[email protected][]^_`{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ¡¢£': No such file or directory 
mv: cannot stat `./áíüűúöőóéÁÍÜŰÚÖŐÓÉ!"#$%&\'()*+,:;<=>[email protected][]^_`{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ¡¢£': No such file or directory 
mv: cannot stat `./áíüűúöőóéÁÍÜŰÚÖŐÓÉ!"#$%&\'()*+,:;<=>[email protected][]^_`{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ¡¢£': No such file or directory 
mv: cannot stat `./áíüűúöőóéÁÍÜŰÚÖŐÓÉ!"#$%&\'()*+,:;<=>[email protected][]^_`{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ¡¢£': No such file or directory 
mv: cannot stat `./áíüűúöőóéÁÍÜŰÚÖŐÓÉ!"#$%&\'()*+,:;<=>[email protected][]^_`{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ¡¢£': No such file or directory 
mv: cannot stat `./áíüűúöőóéÁÍÜŰÚÖŐÓÉ!"#$%&\'()*+,:;<=>[email protected][]^_`{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ¡¢£': No such file or directory 
mv: cannot stat `./áíüűúöőóéÁÍÜŰÚÖŐÓÉ!"#$%&\'()*+,:;<=>[email protected][]^_`{|}~€‚ƒ„…†....and so on 
$ 

так "мв" не может обрабатывать специальные символы ..: \

я работал над ней в течение многих часов ..

у кого-то есть рабочий? [который может обрабатывать символы [имена файлов] в этих двух строках?]

+5

[Accepted rate rate of zero] (http://superuser.com/faq#howtoask) не делает ваш профиль выглядит хорошо. – grawity

+4

Пожалуйста, не перекреститесь (http://serverfault.com/questions/223514/recursive-normalize-filenames). –

+2

Зачем мигрировать от суперпользователя? Это shell-скрипты, а не программирование ... – leppie

ответ

4

Предполагая, что остальная часть вашего скрипта правильная, ваша проблема в том, что вы используете read, но вы должны использовать read -r. Обратите внимание на то, как обратная косая черта исчезла:

áíüűúöőóéÁÍÜŰÚÖŐÓÉ!"#$%&'()*+,:;<=>[email protected][\]^_`{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ¡¢£.txt 
áíüűúöőóéÁÍÜŰÚÖŐÓÉ!"#$%&\'()*+,:;<=>[email protected][]^_`{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ¡¢£ 
17

mv обрабатывает специальные символы просто отлично. У вашего скрипта нет.


В порядке:

  1. Вы используете find, чтобы найти все каталоги и ls каждый каталог отдельно.

    1. Почему for DEPTH in... если вы можете сделать точно такой же, с один команды?

      find -maxdepth 100 -type d 
      
    2. Что делает произвольный предел глубины ненужную

      find -type d 
      
    3. Не никогда разобрать вывод ls, особенно если вы можете позволить find ручку, которая тоже

      find -not -type d 
      
    4. Убедитесь, что она работает в худшем случае:

      find -not -type d -print0 | while read -r -d '' FILENAME; do 
      

      read Это останавливает от употребления в пищу некоторых побегов и задыхается от имен файлов с символами новой строки.

  2. Вы повторяете весьls | replace цикл каждый символов. Не - это убивает производительность. Loop over каждый каталог все файлы один раз, и просто используйте несколько sed или несколько замен в одной команде sed.

    sed 's/á/a/g; s/í/i/g; ...' 
    

    (я собирался предложить sed 'y/áí/ai/', но, к сожалению, это не похоже на работу с Unicode, возможно, perl -CS -Mutf8 -pe 'y/áí/ai/' бы.).

  3. Вы все еще думаете в ASCII: «другие специальные символы - ASCII-коды 33 .. ..255 ". Не.

    1. В эти дни, большинство систем используют Unicode в UTF-8 кодировке, которая имеет много широкого спектра «особых» символы - настолько большого, что перечисление их один за другой, становится бессмысленным. (Это равно multibyte - «e» - один байт, «ė» - три байта.)

    2. True ASCII имеет 128 символов. То, что вы сейчас имеете в виду, - это набор символов ISO 8859 (иногда называемый ANSI) - в частности, ISO 8859-1. Но они доходят до 8859-16, и только часть «ASCII» остается прежней.

  4. echo -n $(command) весьма бесполезно.

  5. Существует гораздо более простой способ найти каталог и базовое имя с заданным путем. Например, вы можете сделать

    directory=$(dirname "$path") 
    oldnname=$(basename "$path") 
    # filter $oldname 
    mv "$path" "$directory/$newname" 
    
  6. ли не использовать egrep, чтобы проверить на наличие ошибок. Проверьте код возврата программы. (Как вы уже это делали с cd.)

  7. И вместо того, чтобы отфильтровывать другие ошибки, сделайте ...

    if [[ -e $directory/$newname ]]; then 
        echo "target already exists, skipping: $oldname -> $newname" 
        continue 
    else 
        mv "$path" "$directory/$newname" 
    fi 
    
  8. Тонна sed 's/------------/-/g' вызовов может быть изменен на один регулярное выражение:

    sed -r 's/-{2,}/-/g' 
    
  9. В [ ] s в tr [foo] [bar] излишни. Они просто вызывают tr для замены [ на [ и ] до ].

  10. Серьезно?

    echo "$FOLDERNAME" | sed "s/$/\//g" 
    

    Как насчет этого вместо этого?

    echo "$FOLDERNAME/" 
    

И, наконец, использовать detox.

+6

+10 только для решения этой проблемы. +10 для детоксикации. К сожалению, 'tr' также не обрабатывает Unicode. В то время как 'grep' понимает классы эквивалентности (' [[= a =]] 'соответствует 'aàâãäå'), не отображаются' sed', 'tr' или' gawk'. –

+0

@Dennis: GNU 'sed' поддерживает' [[= a =]] '. – grawity

6

Попробуйте что-то вроде:

find . -print0 -type f | awk 'BEGIN {RS="\x00"} { printf "%s\x00", $0; gsub("[^[:alnum:]]", "-"); printf "%s\0", $0 }' | xargs -0 -L 2 mv 

Использование xargs (1) будет гарантировать, что каждое имя файла передается именно как один параметр. awk (1) используется для добавления нового имени файла сразу после старого.

Еще один трюк: sed -e 's/- +/-/g' заменит группы более одного «-» ровно одним.

+2

Хорошо, это сексуальное использование awk и xargs. – MikeyB

1

Тьфу ...

Некоторые советы, чтобы очистить свой скрипт:

** Используйте SED, чтобы сделать перевод на несколько символов сразу, что буду убирать вещи и сделать его легче управлять:

dev:~$ echo 'áàaieeé!.txt' | sed -e 's/[áàã]/a/g; s/[éè]/e/g' 
aaaieee!.txt 

** вместо переименования файла для каждого изменения, запустить все ваши фильтры затем сделать один ход

$ NEWNAME='áàaieeé!.txt' 
$ NEWNAME="$(echo "$NEWNAME" | sed -e 's/[áàã]/a/g; s/[éè]/e/g')" 
$ NEWNAME="$(echo "$NEWNAME" | sed -e 's/aa*/a/g')" 
$ echo $NEWNAME 
aieee!.txt 

**, а не делать ls | read ... цикла, использование:

for OLDNAME in $DIR/*; do 
    blah 
    blah 
    blah 
done 

** отделить свой путь обхода и переименовании логики в двух сценариях. Один скрипт находит файлы, которые нужно переименовать, один скрипт обрабатывает нормализацию одного файла. После того, как вы узнаете команду «найти», вы поймете, что можете подбросить первый скрипт :)

+0

Возможно, вы имели в виду «для OLDNAME в« $ DIR »/ * – marco

+0

@marco: назовите его псевдокодом :) На самом деле я удалил его, пытаясь вспомнить, как обойти ошибку кода-блока в списке. – MikeyB

Смежные вопросы