Вопрос Как выполнять команды в другой папке, не повторяя путь к папке?


Есть ли умная способ выполнить операции копирования и перемещения или команду для дублирования файла без необходимости выполнять cd, тогда mv после, в той же папке?

Например, я должен запустить следующее:

mv /folder1/folder2/folder3/file.txt /folder1/folder2/folder3/file-2013.txt

Обратите внимание, что каталог, в котором я перемещаю файл, тот же, но мне нужно снова поместить весь путь, а иногда он раздражает. Мне любопытно узнать, есть ли другой способ сделать это без необходимости повторять весь путь, потому что операция будет выполняться по тому же пути.


72
2018-05-17 12:22


происхождения


Я не могу поверить, что у него так много оборотов. Это дубликат unix.stackexchange.com/questions/35782/... а также unix.stackexchange.com/questions/66889/... - user13107
@ user13107 Есть много способов задать вопрос, включая разные формулировки. И если вы не знаете, что ответ называется «расширение брекета», вы, возможно, не сможете его найти сразу. - slhck
@ user13107 они находятся на другом сайте, поэтому не дублируют - Mark
Марк, спасибо, я не знал этого правила о дубликатах. @slhck Да. Я понимаю. Я был просто расстроен, потому что мой вопрос о Unix.SE был закрыт как дубликат, и этот стал настолько популярным. - user13107
@ user13107, это то, что вы получаете для публикации на правильном сайте - Samuel Edwin Ward


ответы:


Просто используйте расширение скобы:

mv /folder1/folder2/folder3/{file.txt,file-2013.txt}

Это эквивалентно написанию:

mv /folder1/folder2/folder3/file.txt /folder1/folder2/folder3/file-2013.txt

Разумеется, расширение брекетов позволяет вам предоставить больше аргументов. Вы даже можете передавать диапазоны, например. чтобы создать пару тестовых папок, вы можете запустить mkdir test_{a..z}, и начиная с Bash 4, вы также можете создавать нулевые дополнения, как в touch foo{0001..3}, который создает foo0001, foo0002 а также foo0003, Викиреальность есть статья с несколькими примерами для вас.

Если вам нужно использовать две разные команды, используйте подоболочку и cd там, во-первых, как в ответе @ Игнасио,


124
2018-05-17 12:29



Я не знал о brace расширение, спасибо! - Valter Silva
Я пробовал и, похоже, не работает: meniac ~: mv /tmp/f1/f2/f3/f4/f5/f6/{file.txt, file2.txt} mv: cannot stat ``/tmp/f1/f2/f3/f4/f5/f6/{file.txt,': No such file or directory - Valter Silva
Вы уверены, что используете Bash, как в /bin/bash, и вы не в скрипте, который /bin/sh в shebang или какой-либо другой оболочке, которая не поддерживает расширение скобки? Если вы запустите set, делай свое SHELLOPTSсодержать braceexpand? - slhck
Обратите внимание: не должно быть места между file.txt, а также file2.txt, - slhck
Вы можете сделать его еще короче, чтобы предотвратить опечатки в той части, которая не изменяется: mv /folder1/folder2/folder3/file{,-2013}.txt - Jan Fabry


Запустите операцию в подоболочке.

( cd /folder1/folder2/folder3 && mv file.txt file-2013.txt )

Изменение рабочего каталога не будет распространено на родительскую оболочку.


74
2018-05-17 12:24



+1: Мне нравится этот, более переносимый через оболочки, чем трюк с расширением брекета (который аккуратен, но менее портативен) - Olivier Dulac
@Olivier, что заставляет вас думать, что расширение скобки не переносится? Какую оболочку вы имеете в виду, которая ее не поддерживает? - alexis
расширение @alexis Brace не указано POSIX, поэтому оно не переносится «по дизайну». ash, dash, ksh88 не говоря уже о старой оболочке бурны, являются примером оболочек, не поддерживающих ее. - jlliagre
@jlliagre Какая из оболочек, о которой вы говорили, полностью соответствует POSIX? Это означает, что у них не было бы расширения брекетов, даже если это POSIX. ksh88 был до того, как POSIX был ратифицирован; вы должны обновить, по крайней мере, до ksh93. Единственные, кто в Linux позаботится, это зола и тире, поскольку они используются в некоторых небольших встроенных дистрибутивах (busybox, iirc?) И аварийных дисках. - Kaz
@Kaz Я забочусь о переносимости команд оболочки и о том, что они интерактивны или нет, не имеет значения. Конечно, вы, конечно, свободны, чтобы не заботиться об этом, но, пожалуйста, примите, что люди думают иначе. Тот факт, что вы всегда используете bash или оболочку, поддерживающие расширение barce, не означает, что это дело каждого. - jlliagre


Если вы хотите умных, вот bash расширение истории

mv /folder1/folder2/folder3/file.txt !#:1:h/file-2013.txt

Я не стал бы использовать это сам, так как я не могу запомнить его. Я иногда использую эквивалент vim, но нужно искать его почти каждый раз.


21
2018-05-17 13:26





Вы можете установить переменную. Конечно, это имеет побочный эффект, оставляя переменные вокруг.

D=/folder1/folder2/folder3; mv $D/file.txt $D/file-2013.txt

11
2018-05-17 18:01



И, конечно же, вы можете избежать побочного эффекта оставления переменной (-ов), поместив всю командную строку в подоболочку: (D="/folder1/folder2/folder3"; mv "$D"/file.txt "$D"/file-2013.txt), или просто путем добавления unset команды в конце. (Я добавил цитаты как «лучшие практики», если вы привыкли всегда использовать кавычки, вам не придется останавливаться и царапать голову, когда появляется путь, содержащий специальные символы.) - Scott
@Scott, если вы собираетесь использовать подоболочку для устранения побочных эффектов, проще сделать cd чем устанавливать переменную. Не много проще, признаюсь. - Isaac Rabinovitch


Мне нравятся другие решения, но вот еще один, реализованный как скрипт с массивами bash, pushd, popd:

#!/bin/bash
set -e
# from http://stackoverflow.com/a/246128/178651
script_path="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

# paths relative to the script
relative_paths=( \
path1 \
path2 \
path3 \
path4
)

for relative_path in "${relative_paths[@]}"
do
  pushd "$script_path/$relative_path" > /dev/null 2>&1
  pwd
  mv filename1 filename2
  # could do other stuff in this directory...
  popd > /dev/null 2>&1
done

pushd "$script_path" > /dev/null 2>&1
# could do other stuff in same directory as script...
popd > /dev/null 2>&1

2
2018-05-17 20:30





Slhck непосредственно отвечает на вопрос самым простым способом, но Valter также любит автопоп, так вот вот один из них по тем же направлениям;

pushd /folder1/folder2/folder3/; mv file.txt file-2013.txt; popd

1
2018-05-21 22:29