Переименуйте несколько файлов с mv для изменения расширения

Можно использовать следующую команду для изменения на asdf1234 каталог, не указывая имя пользователя:

cd $(find . -name asdf1234 -type d | sed 1q)

sed 1q гарантирует, что только одно имя каталога передается как аргумент cd.

27
29.04.2018, 21:57
7 ответов

Когда вы выдаете команду:

mv *.txt *.tsv

оболочка, давайте предположим bash, расширяет подстановочные знаки , если есть какие-либо совпадающие файлы (включая каталоги). Список файлов передается программе, здесь mv. Если совпадений нет, то передается неисследованная версия.

Снова: shell расширяет шаблоны, а не программу.


Загрузка примеров, пожалуй, лучший способ, так что вот:

Пример 1:

$ ls
file1.txt file2.txt

$ mv *.txt *.tsv

Теперь в строке mv происходит то, что shell расширяет *.txt до совпадающих файлов. Так как не существует файлов *.tsv, которые не были бы изменены.

Команда mv вызывается с двумя специальными аргументами :

  • argc: Количество аргументов, включая программу.
  • argv: Массив аргументов, включающий программу в качестве первой записи.

В приведённом выше примере это было бы:

 argc = 4
 argv[0] = mv
 argv[1] = file1.txt
 argv[2] = file2.txt
 argv[3] = *.tsv

Программа mv проверяет, не является ли последний аргумент, *.tsv каталогом. Так как это не так, программа не может продолжать работу, так как она не предназначена для конкатенации файлов. (Обычно все файлы перемещаются в один.) Нельзя также создавать каталоги по прихоти.

В результате она прерывает работу и сообщает об ошибке:

mv: цель '*.tsv' не является директорией.

Пример 2:

Теперь, если вместо этого сказать:

$ 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

Пример 3:

Если вместо этого сказать:

$ 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".

Пример 4:

Дальнейшее расширение можно посмотреть, например:

$ ls
file1.txt file2.txt

$ mkdir *.txt
mkdir: cannot create directory ‘file1.txt’: File exists
mkdir: cannot create directory ‘file2.txt’: File exists

Пример 5:

Теперь: команда mv может и может работать с несколькими файлами. Но если их больше двух, то последним должен быть целевой каталог. (Опционально вы можете использовать опцию -t TARGET_DIR, по крайней мере, для GNU mv.)

Так что это OK:

$ 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 вообще не упоминается, а переименовывается. Если у Вас есть больше ссылок, Вы можете поделиться ими. Так же, как и для страниц man, где, как вы утверждаете, это выражено.

22
27.01.2020, 19:39

MV * .txt * .tsv не работает; MV может переименовать только один файл за раз. Вы либо неправильно поняли объяснения, либо они неверны.

MMV и Rename может переименовать несколько файлов одновременно. Но есть две версии Rename , которые называются по-разному. Там должно быть много вопросов об этом здесь.

9
27.01.2020, 19:39

Например, если при выполнении команды mv *.txt *.tsv в каталоге имеются asd.txt и qwe.txt файлы, то при выполнении команды mv *.txt *.tsv он пытается переместить эти два файла в каталог с именем *.tsv.  Так как такой директории нет, это дает ошибку.

4
27.01.2020, 19:39

Я знаю, что это не отвечает на Ваш вопрос, но если Вы искали другой способ переименовать файлы по сравнению с Вашим обходным циклом, почему бы не использовать find? Я использовал эту команду много раз, чтобы заменить расширения файлов в больших каталогах на сотни тысяч файлов. Это должно работать на любой POSIX-совместимой системе:

find . -name "*.gappedPeak" -exec sh -c 'mv "$1" "${1%.gappedPeak}.bed"' _ {} \;

Command Breakdown:

  1. '. ' => путь поиска, начинающийся с текущей директории, помеченной ' . '

  2. -name => установить имя поиска совпадений (в этом случае все файлы, которые заканчиваются на .gappedPeak)

  3. -exec => для каждого совпадения

  4. sh -c => 'exec' создает независимое окружение оболочки для каждого совпадения

  5. mv "$1" "${1%". gappedPeak}.bed" => mv первая переменная (обозначена $1), который является текущим именем файла, на новое имя. Здесь я делаю сравнение подстроки и удаляю; поэтому снова возьмите первый var, $1 и используйте % для удаления .gappedPeak из строки. В конце .bed просто соединяет оставшуюся переменную, которая теперь является просто тестом #, с .bed, создавая новый test #.bed.filename.

  6. Подчёркивание - это место для $0

  7. Имя {} заменяется именем каждого (*.gappedPeak) найденного файла. командой найти и становится 1 командой sh .

  8. \; отмечает конец команды -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
32
27.01.2020, 19:39

Другой вариант, который можно рассмотреть, — использование:

cp -p *.txt *.tsv
rm -f *.txt
  • Первая строка копирует все файлы *.txtв *.tsv, сохраняя их атрибуты с помощью флага -p.
  • Вторая строка удаляет все файлы с шаблоном*.txt
  • Для этого метода требуется достаточно места на диске для временного хранения как исходного, так и целевого файлов
  • Этот метод медленнее, чем mv, который просто изменяет /каталог/имя файла без фактического перемещения файлов, если только они не находятся в другом разделе.
0
27.01.2020, 19:39

rename(1)

rename— это Perl-скрипт Ларри Уолла, создателя Perl. Он принимает регулярное выражение Perl и работает с именем файла.

rename 's/\.txt$/.tsv/' *.txt

Установка

Дебиан/Убунту

Если вам нужно установить renameна Debian/Ubuntu, вы можете сделать

sudo apt install rename
3
27.01.2020, 19:39

По-видимому, самый простой способ под ОС Linux:

manual rename

  1. Нажмите на файл
  2. Нажмите F2 (переименовать)
  3. измените имя файла на свое усмотрение
  4. нажмите

Думаю, иногда DOS действительно выигрывает.:)

-1
08.02.2020, 23:10

Теги

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