Виконати конкретну команду в заданому каталозі без cd'ing до неї?


42

Чи є спосіб виконати команду в іншому каталозі, не виконуючи cdїї? Я знаю, що я міг просто входити cdі cdвиходити, але мене просто цікавлять можливості пройти зайві кроки :)


Це досить тривіально , щоб зробити скрипт , який робить це: echo "#!/bin/bash; cd $1; exec $2" > /usr/local/bin/execindirectory; chmod +x /usr/local/bin/execindirectory. Ви можете докласти трохи більше зусиль, якщо ви хочете, щоб він фактично підтримував параметри "тегів", таких як -dі подібні речі.
ЛоуренсC

Як у відповіді невідомі користувачеві, всі приклади, які ви наводили тут, і в коментарях, краще вирішуються іншими рішеннями, тому незрозуміло, чи є насправді проблема, яку тут потрібно вирішити. Чи можете ви придумати кращий приклад?
Калеб

Відповіді:


55

Я не знаю, чи зараховується це, але ви можете зробити підзаголовок:

$ (cd /var/log && cp -- *.log ~/Desktop)

Каталог змінюється лише для цієї підкашти, тож ви уникаєте роботи, необхідної для cd -цього.


2
Ось що я зазвичай роблю.
Адам Бертек

Приємно, я зовсім забув про підкопачі, дуже зручні в даному випадку.
Naftuli Kay

4
Для того, щоб уникнути можливого хаосу, до південь з коми з двома амперсандами: $ (cd /var/log && cp *.log ~/Desktop). Таким чином, якщо каталог не існує, подальші команди не виконуються.
Naftuli Kay

Зауважте, що хтось інший такий наївний, як я: $ at start не є частиною команди, а всього після неї.
Maltronic

14

У деяких програмах є параметри, за допомогою яких ви можете самі їм сказати 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

2
Мені подобається це рішення, за винятком того, що особисто я використовую pushd / popd
NJ

10

Щоб не підірвати значення відповідей інших людей, але я вважаю, що ви хочете, це таке:

(cd /path/to && ./executable [ARGS])

Зверніть увагу на парени для виклику cdв під оболонці.


Я не думаю, що так. Як я розумію, він хоче потрапити в початковий каталог.
Адам Бертек

О, я зовсім забув загорнути це в підкожушок. Виправив мою відповідь, дякую.
alex

4

Ось те, що повинно вас 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

(EDIT: трохи коротша версія, завдяки @ Random832)


1
ви могли просто pushd other-dir, а неpushd .; cd other-dir
Random832

@ Random832, хороший момент!
Бруно

2

На жаль, ваш приклад:

execindirectory -d /var/log "cp *.log ~/Desktop"

не потребує змін до режисера, тому що

cp /var/log/*.log ~/Desktop

зробив би те саме. Ви не можете наблизитися до своєї реальної проблеми? Тому що ми можемо знати і краще рішення для цього.

Складний спосіб вирішити вашу проблему, яка далека від елегантності рішення Майкласа, - це використання знахідки, яка має перемикач '-execdir', який слід виконати в режимі, де знайдений файл. Погано прийнято до вашого прикладу:

find /var/log -maxdepth 1 -type f -name "*.log" -execdir echo cp {} ~/Desktop ";"

Можливо, це корисно для вашої реальної проблеми. -okdir замість -execdir попросить підтвердити кожне виклик.

-okdir та -execdir, можливо, знадобиться встановити gnu-find, який зазвичай використовується в Linux.


1

Як щодо ./your/path/command.sh?


Ні, я на самому справі мав в виду що - щось подібне до наступного: execindirectory -d /var/log "cp *.log ~/Desktop".
Нафтулі Кей

Я прекрасно усвідомлюю, що це не обов'язково, до речі, мене просто цікавить, чи дійсно це можна зробити.
Нафтулі Кей
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.