Я хочу перейменувати файли, щоб змінити їх розширення, ефективно прагнучи виконати
mv *.txt *.tsv
Але при цьому я отримую:
* .tsv не є каталогом
Я вважаю дещо дивним, що перші 10 хітів шоу в Google mv
повинні працювати так.
Я хочу перейменувати файли, щоб змінити їх розширення, ефективно прагнучи виконати
mv *.txt *.tsv
Але при цьому я отримую:
* .tsv не є каталогом
Я вважаю дещо дивним, що перші 10 хітів шоу в Google mv
повинні працювати так.
Відповіді:
Коли ви видаєте команду:
mv *.txt *.tsv
оболонка, дозволяє припустити bash, розширює підстановку, якщо є відповідні файли (включаючи каталоги). Список файлів передається програмі, тут mv
. Якщо не знайдено збігів, розгорнута версія передається.
Знову ж таки: оболонка розширює шаблони, а не програму.
Набір прикладів - це, мабуть, найкращий спосіб, тому ми йдемо:
$ ls
file1.txt file2.txt
$ mv *.txt *.tsv
Тепер у mv
рядку відбувається те, що оболонка розширюється *.txt
до відповідних файлів. Оскільки немає *.tsv
файлів, які не змінюються.
mv
Команда викликається з двома спеціальними аргументами :
argc
: Кількість аргументів, включаючи програму.argv
: Масив аргументів, включаючи програму як перший запис.У наведеному вище прикладі це:
argc = 4
argv[0] = mv
argv[1] = file1.txt
argv[2] = file2.txt
argv[3] = *.tsv
mv
Перевірка програми , щоб побачити , якщо останній аргумент, *.tsv
є каталогом. Як це не так, програма не може продовжуватись, оскільки вона не призначена для об'єднання файлів. (Зазвичай перемістіть усі файли в один.) Не створюйте каталоги за примхою.
Як результат, він перериває і повідомляє про помилку:
mv: target ‘*.tsv’ is not a directory
Тепер якщо ви скажете:
$ mv *1.txt *.tsv
mv
Команда виконується з:
argc = 3
argv[0] = mv
argv[1] = file1.txt
argv[2] = *.tsv
Тепер ще раз mv
перевірте, чи *.tsv
існує. Так як файл file1.txt
не переміщується *.tsv
. Тобто: файл перейменовано на *.tsv
зірочку та всі.
$ mv *1.txt *.tsv
‘file1.txt’ -> ‘*.tsv’
$ ls
file2.txt *.tsv
Якщо ви замість цього сказали:
$ mkdir *.tsv
$ mv *.txt *.tsv
mv
Команда виконується з:
argc = 3
argv[0] = mv
argv[1] = file1.txt
argv[1] = file2.txt
argv[2] = *.tsv
Як і *.tsv
зараз каталог, файли закінчуються переміщенням туди.
Тепер: використовуючи такі команди, як, some_command *.tsv
коли наміром є фактично зберегти підстановку, завжди слід її цитувати. Цитуючи, ви запобігаєте розширенню подвійних кодів, якщо мають бути відповідність. Наприклад, скажімо mkdir "*.tsv"
.
Розширення можна переглянути, якщо ви зробите, наприклад:
$ ls
file1.txt file2.txt
$ mkdir *.txt
mkdir: cannot create directory ‘file1.txt’: File exists
mkdir: cannot create directory ‘file2.txt’: File exists
Тепер: mv
команда може і виконувати роботу над декількома файлами. Але якщо їх більше, то два останніх повинні бути цільовим каталогом. (За бажанням можна скористатися -t TARGET_DIR
опцією, принаймні, для GNU mv.)
Отже, це нормально:
$ ls -F
b1.tsv b2.tsv f1.txt f2.txt f3.txt foo/
$ mv *.txt *.tsv foo
Тут mv
можна назвати:
argc = 7
argv[0] = mv
argv[1] = b1.tsv
argv[2] = b2.tsv
argv[3] = f1.txt
argv[4] = f2.txt
argv[5] = f3.txt
argv[6] = foo
і всі файли потрапляють у каталог foo
.
Що стосується ваших посилань. Ви надали один (у коментарі), де mv
це взагалі не згадується, але rename
. Якщо у вас є більше посилань, ви можете поділитися. Як і для чоловічих сторінок, на яких ви заявляєте, це виражено.
Я знаю, це не відповідає на ваше запитання, але якщо ви шукали інший спосіб перейменувати файли порівняно з циклом обходу, чому б не використати find
? Я багато разів використовував цю команду, щоб замінити розширення файлів у великих каталогах на сотні тисяч файлів. Це має працювати в будь-якій системі, сумісній з POSIX:
find . -name "*.gappedPeak" -exec sh -c 'mv "$1" "${1%.gappedPeak}.bed"' _ {} \;
Розбивка команди:
'
.
' => шлях пошуку, починаючи з поточного каталогу, позначеного символом '. '
-name
=> встановити ім'я пошуку відповідності (у цьому випадку всі файли, які закінчуються.gappedPeak
)
-exec
=> виконайте наступну команду для кожного матчу
sh -c
=> 'exec' створює незалежне середовище оболонки для кожного матчу
mv "$1" "${1%.gappedPeak}.bed"
=>mv
перша змінна (позначена $ 1 ), яка є поточним ім'ям файлу, до нового імені. Тут я збігаю підрядок і видаляю; тому знову візьміть перший var, $ 1 і використовуйте%
для видалення.gappedPeak
з рядка..bed
Зрештою просто приєднує залишилася змінну, яка тепер просто , з , створюючи нове ім'я файлу.test#
.bed
test#.bed
Підкреслення є заповнювачем місця за $ 0
Ім'я
{}
замінюється кожним (*.gappedPeak
) ім'ям файлу, знайденимfind
командою, і стає $ 1 дляsh
команди.
\;
позначає кінець-exec
команди. Ви також можете використовувати';'
або";"
.
Приклад:
[user@before]# ls -lh
total 0
-rw-r--r--. 1 root root 0 Jan 26 11:40 test1.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test2.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test3.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test4.gappedPeak
-rw-r--r--. 1 root root 0 Jan 26 11:40 test5.gappedPeak
[user@after]# ls -lh
total 0
-rw-r--r--. 1 root root 0 Jan 26 11:40 test1.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test2.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test3.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test4.bed
-rw-r--r--. 1 root root 0 Jan 26 11:40 test5.bed
file.abc
-> blub.xyz
у кількох підручниках:find . -name "file.abc" -exec sh -c 'mv "$1" "$(dirname $1)/blub.xyz"' _ {} \;
mv *.txt *.tsv
не працює; mv
може перейменувати лише один файл одночасно. Ви або неправильно зрозуміли пояснення, або вони помиляються.
mmv
і rename
може перейменувати кілька файлів одночасно. Але є дві версії, rename
навколо яких називаються по-різному. Тут має бути багато питань.
rename
, не mv
.
mv *.txt *.tsv
mv
робить (зазвичай) не бачать *.txt
або , *.tsv
але імена файлів оболонки спінені. Кількість файлів, за допомогою яких ці шаблони розширюються, буде "випадковою". Єдина ситуація, коли це працює, якщо є файл з ім'ям, *.txt
яке буде перейменовано на (буквально) *.tsv
(без цитування bash
опція nullglob
не повинна встановлюватися).
foo.txt
і один з ім'ям перезаписує існуючий файл ...baz.tsv
mv *.txt *.tsv
.tsv
Наприклад, якщо у вас є asd.txt
та qwe.txt
файли в каталозі під час виконання команди mv *.txt *.tsv
, вона намагається перемістити ці два файли в каталог з назвою *.tsv
. Оскільки такого каталогу немає, він дає помилку.
rename(1)
rename
це сценарій Perl Ларрі Уолл, виробник Perl. Він займає регулярний вираз Perl і діє на ім'я файлу.
rename 's/\.txt$/.tsv/' *.txt
Якщо вам потрібно встановити rename
Debian / Ubuntu, ви можете це зробити
sudo apt install rename
Ще один варіант, який слід врахувати, - це використання:
cp -p *.txt *.tsv
rm -f *.txt
*.txt
файли *.tsv
, зберігаючи їх атрибути, використовуючи -p
прапор.*.txt
mv
який просто змінює / каталог / ім'я файлу, фактично не переміщуючи файли, якщо вони не перебувають на іншому розділі.