72

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

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

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

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

6 ответов6

124

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

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 . В Bash Hackers Wiki есть статья с несколькими примерами для вас.

Если вам нужно использовать две разные команды, сначала используйте subshell и cd , как в ответе @ Ignacio.

74

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

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

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

21

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

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

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

11

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

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

Мне нравятся другие решения, но вот другое, реализованное в виде скрипта с массивами 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
1

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

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .