2

Я называю файлы по привычке программиста, работающего в командной строке сервера, с подчеркиванием « _ » вместо пробелов « "- потому что из командной строки вы должны избегать пробелов, но это не нужно за пределами командной строки и быстро устареет. Я хотел бы, чтобы при переключении на пробелы все было одинаково.

Из «Терминала» мне интересно, как я могу преобразовать все «x» в «y» в именах файлов для определенного каталога в Mac OS X? Обратите внимание, что «х» означает что угодно, а «у» - просто пробел.

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

6 ответов6

2

Из «Терминала» мне интересно, как я могу преобразовать все «x» в «y» в именах файлов для определенного каталога в Mac OS X? Обратите внимание, что «х» означает что угодно, а «у» - просто пробел.

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

Адаптируя базовую концепцию sed , на которую ссылается @meatspace в своем комментарии (которая находится на этой странице), и добавив find в микс, я придумал этот скрипт:

find . -type d -path '*/\.*' -prune -o -not -name '.*' -type f |\
  while read FULL_ITEM_PATH
  do
    FILE_DIRNAME=$(dirname "${FULL_ITEM_PATH}");
    FILE_BASENAME=$(basename "${FULL_ITEM_PATH}");
    mv "${FILE_DIRNAME}"/"${FILE_BASENAME}" "${FILE_DIRNAME}"/"$(echo $FILE_BASENAME | sed -e 's/_/ /g')";
  done

Он будет использовать команду find чтобы найти все файлы из текущего каталога, в котором вы находитесь, включая дочерние каталоги / файлы, а затем выполнить поиск подчеркиваний в именах файлов (_) и изменить их на пробелы () по желанию. Скрипт игнорирует «точечные файлы» / «невидимые файлы», как .DS_Store через -prune -o -not -name '.*' И тогда основная логика действует только на фактическое имя файла, а не на имя каталога, отделяя базовое имя файла от имени каталога.

Я создал тестовое дерево каталогов на своем компьютере Mac OS X 10.9.5 (Mavericks) с файлами, в именах которых есть подчеркивания (_), а некоторые вложены в дочерний каталог, например так:

./foo_bar
./foo_bar_two
./foo_bar_two_three
./foo_bar_two_three_bleagh.txt
./nested/foo_bar
./nested/foo_bar_two
./nested/foo_bar_two_three
./nested/foo_bar_two_three_bleagh.txt
./nested_foo/foo_bar
./nested_foo/foo_bar_two
./nested_foo/foo_bar_two_three
./nested_foo/foo_bar_two_three_bleagh.txt

Затем я запустил этот скрипт, и все они были автоматически изменены, чтобы использовать пробелы () по желанию вот так:

./foo bar
./foo bar two
./foo bar two three
./foo bar two three bleagh.txt
./nested/foo bar
./nested/foo bar two
./nested/foo bar two three
./nested/foo bar two three bleagh.txt
./nested_foo/foo bar
./nested_foo/foo bar two
./nested_foo/foo bar two three
./nested_foo/foo bar two three bleagh.txt

Пока скрипт работает, если вы хотите выполнить простой «пробный запуск», чтобы увидеть, какие файлы будут действовать в сценарии, замените команду mv чтобы echo так:

find . -type d -path '*/\.*' -prune -o -not -name '.*' -type f |\
  while read FULL_ITEM_PATH
  do
    FILE_DIRNAME=$(dirname "${FULL_ITEM_PATH}");
    FILE_BASENAME=$(basename "${FULL_ITEM_PATH}");
    echo "${FILE_DIRNAME}"/"${FILE_BASENAME}" "${FILE_DIRNAME}"/"$(echo $FILE_BASENAME | sed -e 's/_/ /g')";
  done

Хорошая вещь об использовании echo для отладки в том, что вы также можете точно видеть, что происходит в ядре вашего скрипта. Поэтому, хотя я и написал этот сценарий для точного соответствия потребностям, указанным в этом вопросе, не стесняйтесь экспериментировать с ним, чтобы адаптировать его к новым потребностям / идеям, если они появятся.

0

Для пакетных / сложных задач переименования используйте команду переименования

Например, заменить пробел на _ во всех текстовых файлах в текущей папке.

rename 's/ /_'  *.txt

Переименовать все файлы рекурсивно

find /path/to/target -type f -exec rename 's/ /_/' '{}' \;
0

Я бы, вероятно, использовал Perl для этого.

#!/usr/bin/perl

use strict;
use warnings;

use File::Find;

sub rename_files {
   #skip directories
   return if -d $File::Find::name;

   my $newname = $File::Find::name;
   #turn underscores into space. 
      $newname =~ s/_/ /g; 
   rename $File::Find::name, $newname;
}

find ( \&rename_files, 'path_to_change' ); 
0

Когда в соответствующем каталоге:

for f in in *; do echo mv "$f" "${f/_*_/ }"; done

Это перечислит изменения, которые будут сделаны - удалите echo когда вы хотите, чтобы это действительно сделало переименование. Как и все * nix, есть миллион способов сделать это, но вышеизложенное довольно ясно. Если вы часто делаете эту задачу, подумайте о том, чтобы сохранить ее в bin как скрипт.

-1

Как насчет этого лайнера? (Я надеюсь, что вставка моей команды здесь не испортит пробелы)

for f in `find . -type f -name '*_*'` ; do echo mv "$f" "${f//_/ }"; done        

Кажется, работает, когда я попробовал это. (Вы должны удалить это эхо, когда будете готовы)

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

-2

Там более одной оболочки:

david_koontz @ Macbook: подробнее ~/bin/rename

#!/bin/csh -f

if  ( $1 != "" && $2 != ""  ) then

    foreach file ( `ls *$1*` )
    setenv target  `echo $file | sed s/"$1"/"$2"/`
        if ( -f $file ) then
            echo renaming $file to $target
            mv $file $target
        endif
    end
else
    echo "usage: $0 src_pattern_match  dest_pattern_substitution"
    exit -1
endif
exit 0

И для рекурсивного переименования:

#!/bin/csh -f

    if  ( $1 != "" && $2 != ""  ) then

        # limit the depth search with -maxdepth:

        foreach file ( `find . -maxdepth 8 -iname \*$1\* -type f -exec echo \{\} \;`)
            setenv filehead $file:h
            setenv filetail $file:t
            setenv targettail `echo $filetail | sed s/"$1"/"$2"/`
            echo renaming $file $filehead/$targettail
            mv $file $filehead/$targettail
        end
    else
        "usage: $0 src_pattern_match  dest_pattern_substitution"
        exit -1;
    endif

exit 0;

Для recursive_rename вы можете использовать дополнительный $ 3 для передачи максимальной глубины или исключить -maxdepth 8 , который обеспечивает рекурсивный предел глубины.

Вы можете добавить опцию -i можно добавить в mv или использовать опциональный аргумент для включения интерактивного переименования.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .