Удалить пробелы, дефисы и символы нижнего подчеркивания в именах файлов?

Я рекомендую Вам использовать FreeMind программное обеспечение схемы выражения идей, наряду с vim (плагины установки и использование, это как IDE, от temrinal ;)), учатся использовать терминал и команды Linux, используют Firebug для Firefox, и Chrome's Inspector для веб-отладки Фронтенда использовать Kompozer зафиксировать смешанные отступы тега HTML и почти весь визуальный веб-материал, и многое другое. Я не знаю, ответил ли я на Ваш вопрос или нет, но я понял это таким образом.;) Весело проведите время с Linux :)

10
05.08.2014, 02:28
5 ответов

Версия переименования , которая поставляется с пакетом Perl , поддерживает регулярные выражения:

rename "s/[-_ ]//g" *

альтернативно,

rename -i "s/[-_ ]//g" *

A -I Флаг сделает Rename Использовать интерактивный режим, подсказывая, если цель уже существует, вместо молчаливого перезаписи.

Переименование Perl иногда называется Permate .

Переименование Perl по сравнению с Rename UTIL-Linux

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

На некоторых распределениях Rename Утилита из Util-Linux - это значение по умолчанию. Эта утилита полностью несовместима с Perl Rename .

  • Все: Во-первых, проверьте, если Perl переименовывает , доступно под названием Promaname .

  • Debian: Переименование Perl должно быть по умолчанию. Это также доступно как Perment . Однако переименовывается исполняемый , хотя и находится под управлением / etc / albelianies , и поэтому мог быть изменены на что-то другое.

  • Archlinux: Run PACMAN -S PERL-RENAME и команда доступна как PERL-RENAME . Для более удобного имени создайте псевдоним. (Hat Tip: Chiseledabs)

  • MAC OSX Согласно Этот ответ , , RENAME может быть установлен на OSX, используя домашний интервал через:

     Brew Установить переименование
     
  • Прямая загрузка: Переименование также доступно от Monks Perl:

      wget 'http://www.perlmonks.org/?displaytype=displayCode ;node_id=303814' -O Переименовать
     
11
27.01.2020, 20:00

если у вас есть perl, то вы обычно переименовываете его. Вы можете сделать:

> type rename
rename is /usr/bin/rename

и показать, как этот скрипт написан:

> cat /usr/bin/rename | head -n 5 #firt 5 lines for example
#!/usr/bin/perl -w
#
#  This script was developed by Robin Barker (Robin.Barker@npl.co.uk),
#  from Larry Wall's original script eg/rename from the perl source.
#

Этот скрипт не поддерживает -i флаг (это версия в моей системе), но, возможно, ваша поддерживает. А как же аргументы. Во-первых, это регулярные выражения с форматом PCRE, он работает как фильтр, изменяя входное имя на выходное. Список входных имён, которые вы даёте звездочкой '*'. Например, вы делаете:

> cd /tmp
> rename 's/ //g' *

в реальном выражении '*' может быть расширено до:

> rename 's/ //g' file1 file2 file3 othe files found in current directory

Когда у вас действительно большие count-файлы, вы в ловушке. shell будет расширять вашу строку дольше, чем система принимает. тогда вы можете сделать обходной путь, используя find или xargs. использование 'find' - проблема, потому что переименование будет вызываться много раз, равнозначно количеству файлов в каталоге. лучше использовать xargs с опцией -r. один вызов переименования модифицирует многие файлы. например:

> ls | xargs -r rename 's/ //g'   #thats all, names will be appended at the end of this command.

последняя проблема, что это значит:

's/ //g'

это регулярное выражение для имен модификаций. после первого '/' - пробел. Это обнаруживается и заменяется на строку после второго '/'. Но есть пустая строка, заканчивающаяся третьим '/', затем пробел заменяется ничем. Опция 'g' делает это выражение repetative. выражение будет ходить для всех имен от начала до конца, и обнаруживает все пробелы.

Но что если у вас есть символ табуляции или другой символ 'white'? есть замена для этого '\s'. какие еще ненужные символы? просто добавьте его в выражение. Все заканчивается заключением в скобки, например:

's/[\s_-]//g'

вот и все. видите ли вы сходство? Я думаю, что вам стоит прочитать man perlrequick и man perlretut, это объяснит вам (я надеюсь), как работает регулярное выражение. Вы можете использовать команду переименования в вашем собственном скрипте, если вам это нужно.

.
2
27.01.2020, 20:00

Не считая mv, вам вообще не нужен для этого внешний процесс - вы можете просто poof их попробовать.

ifsqz() ( LC_ALL=C sqz=$1
    isf() { [ -e "$1" ] || [ -L "$1" ] ; }  
    set -- * ; set -f
    for f do isf "$f" || break
    IFS=$sqz; set -- $f; IFS=
    isf "$*" || mv -- "$f" "$*"
    done
)

Тем не менее, это означает mv обращение к каждому файлу, и поэтому, вероятно, переименование лучше. Хотя это должно работать только POSIX mv в $PATH и оболочки POSIX.

Таким образом, я придумал своего рода сумасшедшую демо для этого. Тестовый набор генерируется как:

tee - - - - <<CGEN |\
dd cbs=90 conv=unblock |\
sed 'G;$!N'";s/^/touch -- '/;s/$/'/" |sh
$( #BEGIN CGEN
   LC_ALL=C
   i= n='"$((i=((i=i+1)==10||i==39||i==47)>0?(i+1):i))"'
   printf '%b -_   ---___'  $(
   IFS=0; eval \
       printf '"\\\\%04o\\\\%04o "' "$(
       printf "$n"' "$i" '%s $(
       printf %.252d
#END
))"))
CGEN

В первую очередь я буду первым, кто признает, что вышеприведенная команда дает результаты, которые легче получить другими способами. Но другие средства, скорее всего, не продемонстрируют также, что можно сделать с $IFS и немного (sick?) воображения.

Так что первый бит довольно прямолинейный:

  • tee выдает 5 копий своего входа - наследственный документ под названием CGEN

  • dd блокирует его вход новыми строками на 90 байт на блок и выдает трубки, которые к . ...

  • sed присоединяет 2 из этих блоков к двум \newline символам, 'однозначно цитирует результаты, и готовит строку touch -- для каждого линейного цикла до выхода на . ...

  • sh, который затем выполняет все входные команды в качестве команд оболочки

Бит #CGEN, хотя... Ну, вкратце...

  • нижний printf печатает 252 0s

  • , следующий из последних получает 252 '' null-- string arguments и для каждой печати содержимое $n, за которым следует строка " $i "

  • eval интерпретирует аргументы следующей следующей printf перед печатью результаты этой интерпретации в виде восьмеричных чисел, дополненные 2 обратными слешами на отрезке

  • , последняя printf печатает значения байтов для этих восьмеричных чисел 2 за раз, за которыми следует строка - _ ---___ для каждой пары

  • $n инициализируется до уравнения, которое увеличивает $i на единицу для каждой оценки, за исключением того, что оно пропускает значения 10, 39, или 47 - (которые являются \n ewline, ' единственная цитата, и /косой чертой в ASCII десятичной дроби соответственно)

Конечный результат - каталог, содержащий множество действительно уродливых имен файлов, содержащих каждый байт в моей кодовой таблице от 1 до 255, за исключением единственной цитаты (пропущена только для того, чтобы избежать еще одного sed s/// утверждения) и /косой черты. Эти имена файлов выглядят следующим образом:

(set -- *; printf '%s\n\n##############\n\n%s\n' "${9}" "${34}")  | cat -A

   ---___ww -_   ---___xx -_   ---___yy -_   ---___zz -_   ---___{{ -_   ---___|| -_   ---$
$
___}} -_   ---___~~ -_   ---___^?^? -_   ---___M-^@M-^@ -_   ---___M-^AM-^A -_   ---___M-^BM-^B -_   ---___M-^CM-^C$
$
##############$
$
 -_   ---___M-ZM-Z -_   ---___M-[M-[ -_   ---___M-\M-\ -_   ---___M-]M-] -_   ---___M-^M-^ -_   ---___M-_M-_ -_$
$
---___M-`M-` -_   ---___M-aM-a -_   ---___M-bM-b -_   ---___M-cM-c -_   ---___M-dM-d -_   ---___M-eM-e -_   ---___$

Теперь я получу данные по этим файлам:

chksqz() ( LC_ALL=C sqz=$1
    set -- * ; set -f ; IFS= ; tc="$*"
    printf '#%s\n' \
        "There are $# files in this test directory." \
        "All filenames combined contain a total of ${#tc} bytes."
    IFS=$sqz ; set -- $* ; IFS= ; sc="$*"  
    printf "%s '$sqz'" \
        "#Of which ${#sc} bytes are not"\
        " and $((${#tc}-${#sc})) bytes are"
    set +f ; unset IFS
    printf ".\n#%s\n#Total:\t%d\n#Other:\t%d\n#'$sqz':\t%d\n" \
        "And to confirm these figures:" \
        $(  printf %s * | wc -c 
            printf %s * | tr -d "$sqz" | wc -c
            printf %s * | tr -dc "$sqz" | wc -c
))
chksqz '_ -'

OUTPUT

#There are 101 files in this test directory.
#All filenames combined contain a total of 17744 bytes.
#Of which 2692 bytes are not '_ -' and 15052 bytes are '_ -'.
#And to confirm these figures:
#Total: 17744
#Other: 2692
#'_ -': 15052

Ok. Теперь, наконец, к действию:

ifsqz '_ -'
chksqz '_ -'

OUTPUT

#There are 101 files in this test directory.
#All filenames combined contain a total of 2692 bytes.
#Of which 2692 bytes are not '_ -' and 0 bytes are '_ -'.
#And to confirm these figures:
#Total: 2692
#Other: 2692
#'_ -': 0

Success! Вы можете сами убедиться:

ls

????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
???????????????????????????
???????????????????????????
???????????????????????????
????????????????????????????
????????????????????????????
????????????????
??????????????????????
????????????????????????
??????????????????????????
??????????????????????????
??????????????????????????
??????????????????????????
???????????????????????????
???????????????????????????
???????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
??????????????????????????
????????????????????????
????????????????????
??????????????????
????????????????????????????
??
????????????????????????????
??????????????????????????
????????????????????????????
????????????????????????????
????????????????????!!""##
??????????????????!!""##$$
????????????????!!""##$$%%
????????????!!""##$$%%&&((
????????!!""??##$$%%&&(())
$$%%&&(())**??++,,..0011
%%&&(())**++??,,..00112233
&&(())**++,,??..0011223344
))**++,,..??0011223344556
**++,,..00??11223344556677
22334455667788??99::;;<<==>>
445566778899??::;;<<==>>??@@
5566778899::;;??<<==>>??@@AA
6778899::;;<<??==>>??@@AABB
8899::;;<<==??>>??@@AABBCCDD
\\]]^^``aa??bbccddeeffgghh
]]^^``aabbc??cddeeffgghhii
^^``aabbccdd??eeffgghhiijj
??@@AABBCCDDEE??FFGGHHIIJJKK
AABBCCDDEEFF??GGHHIIJJKKLLM
BBCCDDEEFFGG??HHIIJJKKLLMMNN
CCDDEEFFGGHHII??JJKKLLMMNNOO
EEFFGGHHIIJJ??KKLLMMNNOOPPQQ
ffgghhiijjkk??llmmnnooppqqrr
gghhiijjkkllmm??nnooppqqrrss
iijjkkllmmnn??ooppqqrrsstt
jjkkllmmnnoo??ppqqrrssttuuvv
kkllmmnnooppqq??rrssttuuvvww
LLMMNNOOPPQQRR??SSTTUUVVWWXX
MNNOOPPQQRRSS??TTUUVVWWXXYY
OOPPQQRRSSTT??UUVVWWXXYYZZ[[
PPQQRRSSTTUUVV??WWXXYYZZ[[\\
RRSSTTUUVVWW??XXYYZZ[[\\]]
ssttuuvvwwxx??yyzz{{||}}~~??
ttuuvvwwxxyyz??z{{||}}~~????
uuvvwwxxyyzz{{??||}}~~??????
wwxxyyzz{{||??}}~~??????????
xxyyzz{{||}}~~??????????????
YYZZ[[\\]]^^??``aabbccddee
ZZ[[\\]]^^``??aabbccddeeff
4
27.01.2020, 20:00

Я бы заменил все эти команды tr на команду замены sed, например:

for file in %N; do 
    mv "$file" "$(echo "$file" | sed 's/[ _-]//g')"
done
5
27.01.2020, 20:00

Следующий цикл оболочки sh удалит все пробелы, подчеркивания и тире из имен файлов в текущем каталоге, стараясь не перезаписать существующие файлы:

for f in *; do
    test -f "$f" || continue
    nf=$( echo "$f" | tr -d ' _-' )
    ! test -e "$nf" && echo mv "$f" "$nf"
done

Для bash и ksh, и будучи немного более разборчивым в логике:

for f in *; do
    if [[ -f "$f" ]]; then
        nf=$( tr -d ' _-' <<<"$f" )
        if [[ ! -e "$nf" ]]; then
            echo mv "$f" "$nf"
        fi
    fi
done

Удалите echo, когда вы убедитесь, что он делает то, что вы хотите.

Команда tr удалит (-d) любой символ из заданного набора символов (' _-'). Важно, чтобы тире находилось в самом начале или конце набора, иначе он будет интерпретирован как диапазон символов.

1
27.01.2020, 20:00

Теги

Похожие вопросы