Jak uruchomić jedno polecenie z katalogiem jako argumentem, a następnie cd do tego samego? Otrzymuję „brak takiego pliku lub katalogu”

15

Chciałbym zbudować krótką funkcję, aby wykonać następujące czynności. Powiedzmy, że przenoszę plik „file.tex” do mojego katalogu dokumentów:

mv file.tex ~/Documents

Następnie chciałbym przejść cddo tego katalogu:

cd ~/Documents

Chciałbym uogólnić to na dowolny katalog, aby móc to zrobić:

mv file.tex ~/Documents
follow

i każ followpoleceniu odczytać miejsce docelowe z poprzedniego polecenia, a następnie wykonaj je odpowiednio. W przypadku prostego katalogu nie oszczędza to dużo czasu, ale praca z katalogami zagnieżdżonymi byłaby ogromna, gdyby można było po prostu użyć

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

Myślałem, że będzie to stosunkowo proste i że mogę zrobić coś takiego:

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

ale to nie działa. Jeśli echo $place, otrzymuję żądany ciąg (testuję go ~/Documents), ale zwraca ostatnie polecenie

No such file or directory

Katalog z pewnością istnieje. Jestem zagubiony. Czy możesz mi pomóc?

Ogień
źródło
Chciałbym zaznaczyć, że jeśli nie przeszkadza ci zachowanie file.texoryginalnej lokalizacji, dowiązania symboliczne są bardzo dobrą alternatywą, ponieważ wystarczy tylko raz połączyć, a wtedy zawsze będzie wskazywać najnowszą wersję.
Kroltan
5
Łatwiejszy sposób: wpisz cd alt +, .aby zastąpić ostatni token poprzedniego polecenia. Powtórz tę czynność, aby cofnąć się w historii ostatnich tokenów. (Mówię token nie arg, ponieważ foo &grab &jako ostatni token.) Możesz użyć argumentu numerycznego (na przykład z klawiszem Escape + 3 alt +.).
Peter Cordes,
patrz także combo mkdir cd
Christopher Bottoms

Odpowiedzi:

18

Zamiast definiować funkcję, możesz użyć zmiennej $_, która jest rozwinięta do ostatniego argumentu poprzedniego polecenia o bash. Więc użyj:

cd "$_"

po mvkomendzie.

Możesz także użyć rozszerzenia historii:

cd !:$

Jeśli musisz użyć funkcji:

follow () { cd "$_" ;}

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

Uwaga: Ta odpowiedź jest skierowana na dokładny format argumentów wiersza poleceń, którego użyłeś, gdy mamy do czynienia z parametrami pozycyjnymi. W przypadku innych formatów, np. mv -t foo bar.txtKonieczne jest wcześniejsze włączenie określonych kontroli, wówczas odpowiednie byłoby opakowanie.

heemayl
źródło
Twoja ekspansja historii (cd!: $) Działa idealnie. Dziękuję Ci. Jednak drugi (cd „$ _”) nie: mv file.tex ~ / Downloads / cd "$ _" bash: cd: __bp_preexec_invoke_exec: Nie ma takiego pliku ani katalogu Z przyjemnością zaakceptuję twoją odpowiedź jako całkowicie poprawną, i Dziękuję Ci.
Ogień
Ja zawsze wpisany (nieco rozrzutnie) albo cd !$albo cd $(dirname !$). Nie wiedziałem o $_zmiennej!
Kalvin Lee
Co się stanie, jeśli zrobię to mv -t ~/Documents file.texzamiast mv file.tex ~/Documents? Podsumowując, nie jestem pewien, czy jest to możliwe do rozwiązania w ogólnym przypadku ... funkcja otoki lub że reimplementacja mvmoże być lepsza ...
CVn
@ MichaelKjörling Nie zadziała po prostu .. ten przykład dotyczy tylko przypadku, w którym OP ma, a nie
skrajnych
Nie potrzebujesz okrężnicy; !$jest równoważne !:$i szybsze w pisaniu.
Wildcard,
14

W przypadku standardowych skrótów klawiszowych kombinacja Alt.skopiuje ostatni argument poprzedniego wiersza poleceń do bieżącego. Więc pisanie

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

poddałby się

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

i byłoby jeszcze mniej pisania niż słowo follow.

Dla większej wygody powtarzanie Alt.kombinacji spowoduje przeglądanie ostatnich argumentów wszystkich poprzednich linii poleceń.

Dodatek: Nazwa polecenia bash odpowiadająca tej kombinacji klawiszy to yank-last-arglub insert-last-argument. Można go znaleźć na stronie podręcznika bash pod „Poleceniami do manipulowania historią” lub w bardziej wyczerpującym podręczniku Bash Reference Manual ).

Dubu
źródło
1
To sprytne. Dzięki! Nie miałem pojęcia, że ​​to istnieje.
Pożar
@Fire Dodałem referencje do tych poleceń, dzięki czemu można znaleźć o wiele bardziej interesujące powiązania klawiszy (i od razu je zapomnieć, jak zawsze).
Dubu
1
Możesz także użyć <esc>tego, .aby uzyskać ten sam wynik <alt>+., co jest użyteczne, gdy
zamapowałeś Capslocka,
1
@gnur vi (m) użytkownik, jak sądzę. ;-)
Dubu
6

Prawie na pewno napotykasz problem polegający na tym, że rozwinięcie tyldy występuje przed rozwinięciem parametru, co można wyjaśnić zwięzłym przykładem:

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

Można to rozwiązać za pomocą eval. W każdym razie będziesz potrzebować eval, ponieważ pobierasz polecenia z historii i mogą one zawierać dowolne rozszerzenia, takie jak:

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

(Występują problemy, takie jak to, że ponowna interpretacja tych wartości może już nie pasować do pierwotnej interpretacji, która miała miejsce. Załóżmy, że compute_folder_namejest to funkcja zwiększająca pewną zmienną globalną.)

Kaz
źródło
4
Nie trzeba eval. (Zawsze.) Ale dobre wyczuwanie problemów z sekwencją rozszerzeń. Jeśli wspomnisz o większej celowości poszerzenia historii korzystania z tego evalmiejsca, będzie to moim zdaniem najlepsza odpowiedź; żadne z pozostałych nie wyjaśniło, dlaczego rozwiązanie Original Poster nie zadziałało.
Wildcard,