Як я можу використовувати подвійні картки стилю ms-dos з ls та mv?


9

У мене нещастя походить із MS-DOS, але принаймні це змушує мене оцінити, наскільки потужніший Linux. Я працював над тим, щоб зрівняти свій Linux-Fu, але є кілька речей, які можна зробити з DOS, що я не впевнений, як це зробити найпростіше з Linux:

Перейменування декількох файлів - використання двох марок

c:\> dir

Directory of c:\
    file1.txt
    file2.txt
    file3.txt
    file4.txt

c:\>rename *.txt *.bak

c:\> dir

Directory of c:\
    file1.bak
    file2.bak
    file3.bak
    file4.bak

Я знаю, що я міг би використати find -execтут, але можливо використовувати коротший синтаксис - можливо, mvз якимись спеціальними прапорами чи синтаксисом? Я думаю, що ключовим у цьому є другий * підстановочний код, оскільки у Linux не повинно виникнути проблем із першим (тобто я знаю, як вибрати файли, які я хочу перейменувати за допомогою символів)

Перейменування одного файлу - використання однієї підстановки

c:\> dir

Directory of c:\
    file1.txt

c:\>rename file1.txt *.bak

c:\> dir

Directory of c:\
    file1.bak

Це буде особливо корисно при перейменуванні довгих і громіздких імен файлів. Я подумав, що, можливо, я міг би використати mv file1.txt $1.bakдля завершення те, file1.txt.bakщо також було б прийнятним, але я не впевнений, що ви можете посилатись на $1параметр inline командою shell. Знову ж таки, у цьому конкретному випадку просто зручно, як ms-dos bastardizes *підстановку використовувати як своєрідну відповідність захоплення / заміни частини назви файлу.

Фільтрування списків каталогів з підстановкою

c:\> dir

Directory of c:\
    file1.txt
    file2.txt
    file3.txt
    file4.txt
    text.txt
    \temp       (directory) 

c:\> dir file*

Directory of c:\
    file1.txt
    file2.txt
    file3.txt
    file4.txt

c:\> t*

Directory of c:\
    text.txt
    \temp       (directory) 

Я не впевнений, який правильний синтаксис для цього ls, або якщо це навіть можливо. Якщо я зробив щось подібне, ls t*він повториться в каталогах, починаючи з t. Моє вирішення використовувалось find . --max-depth 1 -iname "t*"або щось подібне ls -al | grep t- жодне з них не таке коротке і просте, як dir t*є.

Нарешті, я знаю, що я можу налаштувати псевдоніми, щоб зробити ці довгі команди коротшими, але я хотів би навчитися виконувати ці речі поза вікном linux-fu, тому що іноді ви підключені до віддаленої системи або працюєте на новій машині.

Тож як я можу mvі lsфайли виконувати так само, як раніше, dirі renameфайли?

Відповіді:


15

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

Але є 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

дуже хороший! я думаю, що я щойно пересунувся на поясі зі своїм Linux-фу! Дякую!
cwd

Порада, щоб трохи просунутись із цим (і уникати підводних каменів): використовуйте прості функції або сценарії, щоб побачити, що відбувається, якщо ви робите це, somefunc *.Extякщо цей шаблон не відповідає жодному файлу, і грайте з цитуванням, щоб побачити, чи вдалося вам передати шаблон навколо ( без розширення) між функціями. Порада з безпеки: ніде не використовуйте ніколиrm , експериментуючи з розширенням глобуса / оболонки :-)
Мат

4

Одне, що потрібно пам’ятати, коли мова заходить про макі символи - це те, що вони розширені оболонкою. Додаток не знає, чи використовували Ви макіяж символів чи вводили імена. Наприклад, якщо ви вводите 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 як свою оболонку (це має інші переваги над bash) і помістити ці рядки у ваше ~/.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(завжди потрібно захистити $текст, що заміняється).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.