Есть ли способ выполнить команду в другом каталоге без необходимости cd
? Я знаю, что мог бы просто входить cd
и cd
выходить, но меня просто интересуют возможности отказаться от лишних шагов :)
Есть ли способ выполнить команду в другом каталоге без необходимости cd
? Я знаю, что мог бы просто входить cd
и cd
выходить, но меня просто интересуют возможности отказаться от лишних шагов :)
Ответы:
Я не знаю, считается ли это, но вы можете сделать подоболочку:
$ (cd /var/log && cp -- *.log ~/Desktop)
Каталог изменяется только для этой подоболочки, поэтому вы можете избежать необходимости в cd -
последующем.
$ (cd /var/log && cp *.log ~/Desktop)
. Таким образом, если каталог не существует, дальнейшие команды не выполняются.
У некоторых программ есть опции, с помощью которых вы можете сказать им самим chdir (2) (например, GNU tar 's -C
/ --directory
).
За пределами таких программ что-то придется чдир . Вы могли бы написать и использовать какую-то скомпилированную «двоичную» программу вместо того, чтобы оболочка делала это, но это, вероятно, не принесло бы большой пользы.
В комментарии к другому ответу вы привели пример:
execindirectory -d /var/log "cp *.log ~/Desktop"
Так как *.log
шаблон расширяется самой оболочкой (не cp ), что-то должно будет chdir в каталог, прежде чем оболочка оценит вашу команду.
Если вам просто интересно избегать «cd back», то вы можете использовать подоболочку, чтобы изолировать эффект cd от вашего рабочего экземпляра оболочки.
(cd /path/to/dir && some command)
Вы можете упаковать это в функцию оболочки. (Я исключил эту -d
опцию из вашего примера использования, поскольку эта команда не имеет смысла, если каталог на самом деле необязательный.)
runindir() { (cd "$1" && shift && eval "$@"); }
runindir /var/log 'cp *.log ~/Desktop' # your example
runindir /var/log cp \*.log \~/Desktop # eval takes multiple args
runindir /var/log cp \*.log ~/Desktop # it is okay to expand tilde first
Не для того, чтобы подорвать ценность ответов, данных другими людьми, но я верю, что вы хотите вот что:
(cd /path/to && ./executable [ARGS])
Обратите внимание на парены, которые нужно вызывать cd
в под-оболочке.
Вот кое-что, что должно cd
вернуть вас туда, где вы были (используя Bash), так как цель этого вопроса - не забыть сделать это:
# Save where you are and cd to other dir
pushd /path/to/dir/that/needs/to/be/current/dir
run-your-command
# Get back where you were at the beginning.
popd
(РЕДАКТИРОВАТЬ: немного короче версия, благодаря @ Random832)
pushd other-dir
, а неpushd .; cd other-dir
К сожалению, ваш пример:
execindirectory -d /var/log "cp *.log ~/Desktop"
не нужно менять каталог, потому что
cp /var/log/*.log ~/Desktop
сделал бы то же самое. Разве вы не можете приблизиться к своей реальной проблеме? Потому что мы могли бы знать и лучшее решение для этого.
Сложным способом решения вашей проблемы, который далек от элегантности решения Michaels, является использование команды find, которая имеет ключ '-execdir', который должен выполняться в директории, где находится файл. Плохо принят по вашему примеру:
find /var/log -maxdepth 1 -type f -name "*.log" -execdir echo cp {} ~/Desktop ";"
Может быть, это полезно для вашей реальной проблемы. -okdir вместо -execdir попросит вас подтвердить каждый вызов.
-okdir и -execdir, возможно, потребуется установить gnu-find, который обычно используется в Linux.
Как насчет ./your/path/command.sh
?
execindirectory -d /var/log "cp *.log ~/Desktop"
.
echo "#!/bin/bash; cd $1; exec $2" > /usr/local/bin/execindirectory; chmod +x /usr/local/bin/execindirectory
. Возможно, потребуется приложить немного больше усилий, если вы хотите, чтобы он действительно поддерживал опцию "тегов", таких как-d
и прочее.