Можно использовать следующую команду для изменения на asdf1234 каталог, не указывая имя пользователя:
cd $(find . -name asdf1234 -type d | sed 1q)
sed 1q
гарантирует, что только одно имя каталога передается как аргумент cd
.
Когда вы выдаете команду:
mv *.txt *.tsv
оболочка, давайте предположим bash, расширяет подстановочные знаки , если есть какие-либо совпадающие файлы (включая каталоги). Список файлов передается программе, здесь mv
. Если совпадений нет, то передается неисследованная версия.
Снова: shell расширяет шаблоны, а не программу.
Загрузка примеров, пожалуй, лучший способ, так что вот:
$ 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' не является директорией.
Теперь, если вместо этого сказать:
$ 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.)
Так что это 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, где, как вы утверждаете, это выражено.
MV * .txt * .tsv
не работает; MV
может переименовать только один файл за раз. Вы либо неправильно поняли объяснения, либо они неверны.
MMV
и Rename
может переименовать несколько файлов одновременно. Но есть две версии Rename
, которые называются по-разному. Там должно быть много вопросов об этом здесь.
Например, если при выполнении команды mv *.txt *.tsv
в каталоге имеются asd.txt
и qwe.txt
файлы, то при выполнении команды mv *.txt *.tsv
он пытается переместить эти два файла в каталог с именем *.tsv
. Так как такой директории нет, это дает ошибку.
Я знаю, что это не отвечает на Ваш вопрос, но если Вы искали другой способ переименовать файлы по сравнению с Вашим обходным циклом, почему бы не использовать find
? Я использовал эту команду много раз, чтобы заменить расширения файлов в больших каталогах на сотни тысяч файлов. Это должно работать на любой POSIX-совместимой системе:
find . -name "*.gappedPeak" -exec sh -c 'mv "$1" "${1%.gappedPeak}.bed"' _ {} \;
Command Breakdown:
'
.
' => путь поиска, начинающийся с текущей директории, помеченной ' . '
-name
=> установить имя поиска совпадений (в этом случае все файлы, которые заканчиваются на.gappedPeak
)
-exec
=> для каждого совпадения
sh -c
=> 'exec' создает независимое окружение оболочки для каждого совпадения
mv "$1" "${1%". gappedPeak}.bed"
=>mv
первая переменная (обозначена $1), который является текущим именем файла, на новое имя. Здесь я делаю сравнение подстроки и удаляю; поэтому снова возьмите первый var, $1 и используйте%
для удаления.gappedPeak
из строки. В конце.bed
просто соединяет оставшуюся переменную, которая теперь является простотестом #
, с.bed
, создавая новыйtest #.bed
.filename.Подчёркивание - это место для $0
Имя
{}
заменяется именем каждого (*.gappedPeak
) найденного файла. командойнайти
и становится 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
Другой вариант, который можно рассмотреть, — использование:
cp -p *.txt *.tsv
rm -f *.txt
*.txt
в *.tsv
, сохраняя их атрибуты с помощью флага -p
.*.txt
mv
, который просто изменяет /каталог/имя файла без фактического перемещения файлов, если только они не находятся в другом разделе. rename(1)
rename
— это Perl-скрипт Ларри Уолла, создателя Perl. Он принимает регулярное выражение Perl и работает с именем файла.
rename 's/\.txt$/.tsv/' *.txt
Если вам нужно установить rename
на Debian/Ubuntu, вы можете сделать
sudo apt install rename
По-видимому, самый простой способ под ОС Linux:
Думаю, иногда DOS действительно выигрывает.:)