Я хочу перейменувати файли, щоб змінити їх розширення, ефективно прагнучи виконати
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#.bedtest#.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.tsvmv *.txt *.tsv.tsv
Наприклад, якщо у вас є asd.txtта qwe.txtфайли в каталозі під час виконання команди mv *.txt *.tsv, вона намагається перемістити ці два файли в каталог з назвою *.tsv. Оскільки такого каталогу немає, він дає помилку.
rename(1)renameце сценарій Perl Ларрі Уолл, виробник Perl. Він займає регулярний вираз Perl і діє на ім'я файлу.
rename 's/\.txt$/.tsv/' *.txt
Якщо вам потрібно встановити renameDebian / Ubuntu, ви можете це зробити
sudo apt install rename
Ще один варіант, який слід врахувати, - це використання:
cp -p *.txt *.tsv
rm -f *.txt
*.txtфайли *.tsv, зберігаючи їх атрибути, використовуючи -pпрапор.*.txtmvякий просто змінює / каталог / ім'я файлу, фактично не переміщуючи файли, якщо вони не перебувають на іншому розділі.