Как я могу использовать подстановочные знаки стиля MS-DOS с ls и mv?

rename stringx stringy stringx.*

Существует (по крайней мере) две названные утилиты rename в типичных системах Linux. Debian и полученные дистрибутивы (включая Ubuntu) поставляют сценарий Perl, синтаксис которого был бы

rename 's/stringx/stringy/' stringx.*

На других дистрибутивах, включая CentOS, rename от util-linux, и его синтаксис - то, что я записал выше. Эта утилита доступна под именем rename.ul на Debian и производных.

Если Вы хотите рекурсивно вызвать в подкаталогах, предполагая csh значение tcsh (но действительно, думайте о вводе середины 1990-х и переключении на zsh):

set globstar
rename stringx stringy stringx.* **/stringx.*
9
07.01.2012, 18:18
2 ответа

Одно из принципиальных различий между Windows cmd и оболочки POSIX - то, кто ответственен за подстановочные расширения. Оболочки делают все расширения, требуемые прежде, чем запустить фактические команды, которые Вы попросили. cmd главным образом передает подстановочные шаблоны неизмененным командам. (Я говорю главным образом, так как я думаю, что существуют исключения, и переменные среды расширены при большинстве обстоятельств.) Это делает запись a rename это работало бы с тем же синтаксисом как в cmd довольно хитрый.

Но существует a rename для Linux - с совершенно другими аргументами, проверьте страницу справочника (который является немного кратким в моей системе, и rename прибывает из util-linux пакет в моей системе, которая должна быть широко доступной). Ваши первые переименовывают, был бы сделан как это:

rename .txt .bak *.txt

Обратите внимание, что оболочка делает * расширение, таким образом, rename самостоятельно на самом деле думает, что это было вызвано как это:

rename .txt .bak file1.txt file2.txt file3.txt ...

Таким образом, можно предположить единственную версию файла:

rename .txt .bak file1.txt

Если Вы не хотите использовать rename но реализуйте это сами, Вы могли создать функцию для этого. Принятие Вас только хочет изменить расширение файла, и для однофайлового переименовывают, смотрят на это:

$ function chext() {
  newext="$1"
  file="$2"
  newfile="${file%.*}$newext"
  echo mv "$file" "$newfile"
}
$ chext .csv test.txt
mv text.txt text.csv

$newfile создается с помощью удаления подстроки для разделения первоначального внутреннего абонента, затем связывает новое расширение. Можно расширить ту функцию для обработки нескольких файлов относительно легко.


Что касается Вашего ls вопрос, используйте -d переключатель. Это предотвратит ls из списка содержания каталогов.

Демонстрация:

$ ls -al
total 536
drwx------   3 owner users 528384 Jan  7 17:29 .
drwxr-xr-x 126 owner users  12288 Jan  7 17:26 ..
-rw-r--r--   1 owner users      0 Jan  7 17:28 f1.csv
-rw-r--r--   1 owner users      0 Jan  7 17:28 f2.csv
-rw-r--r--   1 owner users      0 Jan  7 17:28 f3.csv
-rw-r--r--   1 owner users      0 Jan  7 17:28 f4.csv
drwxr-xr-x   2 owner users   4096 Jan  7 17:33 test
-rw-r--r--   1 owner users      0 Jan  7 17:27 test.csv

Подстановочный знак переименовывает

$ rename .csv .txt f*
$ ls -al
total 536
drwx------   3 owner users 528384 Jan  7 17:34 .
drwxr-xr-x 126 owner users  12288 Jan  7 17:26 ..
-rw-r--r--   1 owner users      0 Jan  7 17:28 f1.txt
-rw-r--r--   1 owner users      0 Jan  7 17:28 f2.txt
-rw-r--r--   1 owner users      0 Jan  7 17:28 f3.txt
-rw-r--r--   1 owner users      0 Jan  7 17:28 f4.txt
drwxr-xr-x   2 owner users   4096 Jan  7 17:33 test
-rw-r--r--   1 owner users      0 Jan  7 17:27 test.csv

Однофайловый переименовывают

$ rename .txt .csv f1.txt 
$ ls -al
total 536
drwx------   3 owner users 528384 Jan  7 17:34 .
drwxr-xr-x 126 owner users  12288 Jan  7 17:26 ..
-rw-r--r--   1 owner users      0 Jan  7 17:28 f1.csv
-rw-r--r--   1 owner users      0 Jan  7 17:28 f2.txt
-rw-r--r--   1 owner users      0 Jan  7 17:28 f3.txt
-rw-r--r--   1 owner users      0 Jan  7 17:28 f4.txt
drwxr-xr-x   2 owner users   4096 Jan  7 17:33 test
-rw-r--r--   1 owner users      0 Jan  7 17:27 test.csv

Значение по умолчанию ls

$ ls -l t*
-rw-r--r-- 1 owner users    0 Jan  7 17:27 test.csv

test:
total 0
-rw-r--r-- 1 owner users 0 Jan  7 17:33 dont_show_me_please

ls это не осматривает каталоги

$ ls -ld t*
drwxr-xr-x 2 owner users 4096 Jan  7 17:33 test
-rw-r--r-- 1 owner users    0 Jan  7 17:27 test.csv
15
27.01.2020, 20:05
  • 1
    ! я думаю, что только что переместил пояс вверх со своим linux-fu!спасибо! –  cwd 07.01.2012, 19:15
  • 2
    Подсказка, чтобы сделать успехи немного с этим (и избежать ловушек): используйте простые функции или сценарии для наблюдения то, что происходит, когда Вы делаете somefunc *.Ext если тот шаблон не соответствует никакому файлу и играет с заключением в кавычки, чтобы видеть, удается ли Вам раздать шаблон (не разворачивая его) между функциями. Мера предосторожности: не использовать rm где угодно при экспериментировании с globbing/shell расширением :-) –  Mat 07.01.2012, 19:24

Одна вещь иметь в виду когда дело доходит до подстановочных знаков состоит в том, что они расширены оболочкой. Приложение не знает, использовали ли Вы подстановочные знаки или ввели имена. Например, если Вы вводите rename *.txt *.bak, затем rename команда видит что-то как rename file1.txt file2.txt existingfile.bak. Это - недостаточно информации для продолжения.

Я буду иметь дело с вопросом о ls во-первых, потому что это более просто. Если все, что Вы хотите, является именами соответствия, то Вам не нужно ls, потому что оболочка уже делает расширение.

echo t*

Если Вы хотите больше информации о файлах, то передаете -d опция к ls, сказать этому не перечислять содержание каталогов.

ls -ld t*

Нет никакой стандартной утилиты для переименования файлов, потому что первые системы Unix не шли с тем. Портативный метод для переименования файлов использует цикл и является немного подробным:

for x in *.txt; do mv -- "$x" "${x%.txt}.bak"; done

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

  • rename от util-linux комплект, доступный в каждой невстроенной системе Linux (и больше нигде). На Debian и производных (включая Ubuntu), называют эту команду rename.ul. При условии, что нет никакого возникновения .txt кроме заключительного расширения, можно записать

    rename .txt .bak *.txt
    
  • rename сценарий Perl, который Debian и производные поставляют как /usr/bin/rename. Можно переименовать файлы согласно произвольным командам Perl.

    rename 's/\.txt\z/\.bak/' *.txt
    
  • mmv, который может переименовать, копия и файлы связей согласно нескольким основанным на имени шаблонам и имеет много опций, касающихся, что происходит, если целевое имя уже существует. Обратите внимание, что необходимо использовать кавычки для защиты подстановочных знаков от расширения оболочкой.

    mmv '*.txt' '#1.txt'
    
  • zmv функция zsh, доступная, если и только если Ваша оболочка является zsh. Это может соответствовать произвольным zsh шаблонам (таким образом, можно соответствовать именам файлов согласно произвольным регулярным выражениям, не только подстановочным знакам, и можно соответствовать файлам по другим критериям, таким как даты и размеры). zmv может также скопировать и связаться.

    zmv '(*).txt' '$1.txt'
    

Если Вы имеете некоторый контроль над машинами, Вы используете, моя рекомендация состоит в том, чтобы использовать zsh в качестве Вашей оболочки (это обладает другими преимуществами по удару), и вставьте эти строки Ваш ~/.zshrc:

autoload -U zmv
alias zmv='noglob zmv -w'
alias zcp='zmv -C'
alias zln='zmv -L'
alias zsy='zmv -Ls'

noglob zsh функция, которая говорит оболочке не разворачивать подстановочные знаки в аргументе команды. Таким образом, можно записать zmv *.txt \$1.txt (необходимо будет всегда защищать $ в тексте замены).

4
27.01.2020, 20:05

Теги

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