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?


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,


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.


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 ).


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ą.)


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,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.