Як запустити одну команду з каталогом як аргумент, а потім CD до тієї ж? Я отримую "немає такого файлу чи каталогу"


15

Я хотів би побудувати коротку функцію, щоб зробити наступне. Скажімо, я переміщую файл "file.tex" в каталог своїх документів:

mv file.tex ~/Documents

Потім я хотів би перейти cdдо цього каталогу:

cd ~/Documents

Я хотів би узагальнити це до будь-якого каталогу, щоб я міг це зробити:

mv file.tex ~/Documents
follow

і попросіть followкоманду прочитати призначення з попередньої команди, а потім виконати відповідно. Для простого каталогу це не економить багато часу, але при роботі з вкладеними каталогами було б надзвичайно просто користуватися

mv file.tex ~/Documents/folder1/subfolder1
follow

Я думав, що це буде досить просто, і що я можу зробити щось подібне:

follow()
{
    place=`history 2 | sed -n '1p;1q' | rev | cut -d ' ' -f1 | rev`
    cd $place
}

але це, здається, не працює. Якщо я лунаю $place, я отримую потрібний рядок (тестую його ~/Documents), але остання команда повертається

No such file or directory

Каталог, безумовно, існує. Я в збитку. Не могли б ви мені допомогти?


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

5
Найпростіший спосіб: введіть cd alt +, .щоб замінити останній маркер попередньої команди. Повторіть, щоб повернутися в історію остаточних жетонів. (Я кажу токен не аргумент, тому що foo &сприймає &як кінцевий маркер.) Ви можете використовувати числовий аргумент (наприклад, з escape-3 alt +. Наприклад).
Пітер Кордес


дивіться також mkdir CD combo
Christopher Bottoms

Відповіді:


18

Замість того, щоб визначити функцію, ви можете використовувати змінну $_, розширену до останнього аргументу попередньої команди bash. Тому використовуйте:

cd "$_"

після mvкоманди.

Ви також можете використовувати розширення історії:

cd !:$

Якщо вам потрібно скористатися функцією:

follow () { cd "$_" ;}

$ follow () { cd "$_" ;}
$ mv foo.sh 'foo bar'
$ follow 
foo bar$ 

Примітка: Ця відповідь спрямована на точний формат аргументів командного рядка, який ви використовували, коли ми маємо справу з позиційними параметрами. Для інших форматів, наприклад mv -t foo bar.txt, потрібно заздалегідь включити конкретні перевірки, тоді було б доречно обгортку.


Ваше розширення історії (cd!: $) Працює чудово. Дякую. Однак інший (cd "$ _") не: mv file.tex ~ / Downloads / cd "$ _" bash: cd: __bp_preexec_invoke_exec: Немає такого файлу чи каталогу, я дуже з радістю прийму вашу відповідь як цілком правильну, і Дякую.
Пожежа

Я завжди набирав (дещо марнотратно) cd !$або cd $(dirname !$). Не знав про $_змінну!
Калвін Лі

Тепер, що станеться, якщо я роблю mv -t ~/Documents file.texзамість цього mv file.tex ~/Documents? Підсумок, я не впевнений, що це можна вирішити в загальному випадку ... функція обгортки навколо або що повторне виконання mvможе бути краще ...
CVn

@ MichaelKjörling Не буде працювати просто. Цей приклад - це просто висвітлити справу ОП, а не крайові (або всі) випадки ..
heemayl

Товста кишка вам не потрібна; !$еквівалентно !:$та швидше набирається.
Wildcard

14

За допомогою стандартних клавіш bash комбінація Alt.буде копіювати останній аргумент попереднього командного рядка в поточний. Отже, набираючи текст

$ mv foo ~/some/long/path/
$ cd <Alt><.>

дасть урожай

$ mv foo ~/some/long/path/
$ cd ~/some/long/path/

і було б навіть менш набраним, ніж слово follow.

Для додаткової зручності повторення Alt. комбінації перегляне останні аргументи всіх попередніх командних рядків.

Додаток: Назва команди bash, що відповідає цій комбінації клавіш, є yank-last-argабо insert-last-argument. Його можна знайти на сторінці bash у розділі "Команди для маніпуляції історією" або у більш вичерпному посібнику Bash .)


1
Це розумно. Спасибі! Я не мав уявлення, що це існує.
Вогонь

@Fire Я додав посилання на ці команди, тому ви можете знайти набагато цікавіші прив'язки клавіш (і негайно забути їх знову, як я завжди роблю).
Дубу

1
Ви також можете використовувати <esc>тоді, .щоб отримати такий же результат, як <alt>+.це, корисно, коли ви
перезавантажили капсул

1
Я думаю, користувач @gnur vi (m). ;-)
Дубу

6

Ви майже напевно стикаєтеся з проблемою, що розширення tilde відбувається перед розширенням параметра, що можна пояснити стислим прикладом:

$ cd ~kaz
kaz $ var='~kaz'
kaz $ echo $var
~kaz
kaz $ cd $kaz
bash: cd: ~kaz: No such file or directory

Це можна вирішити eval. У будь-якому випадку вам знадобиться eval, тому що ви тягнете команди з історії, і вони можуть містити довільні розширення, наприклад:

$ mv file.tex ~/Documents/$(compute_folder_name foo-param)/subfolder1
$ follow

(Існують такі проблеми, як, наприклад, повторне розширення цих значень більше не може відповідати початковому розширенню. Припустимо compute_folder_name, це функція, яка збільшує деяку глобальну змінну.)


4
Вам не потрібно eval. (Ніколи.) Але добре помітити проблеми з послідовністю розширення. Якщо ви згадаєте про більшу доцільність розширення історії для використання evalтут, це, на мій погляд, буде найкращою відповіддю; ніхто з інших насправді не пояснює, чому рішення оригінального плаката не спрацювало.
Wildcard
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.