realpath
i readlink
zwracaj ścieżki bezwzględne:
+akiva@X230:~$ realpath ZannaIsAwesome
/home/akiva/ZannaIsAwesome
Z taką ścieżką łatwo sobie poradzić. Jednak coś takiego będzie miało pewne problemy:
Na przykład:
Tak więc nazwa taka musi zostać zdezynfekowana, aby móc przekazać ją innym poleceniom. Przypadkiem użycia może być coś takiego:
+a@X230:~/\e[92mM@r|< $hu+'|'|_e|\|\|0rth [`-_-"]$ bacon=$(realpath pullingATerdon)
+a@X230:~$ vim $bacon
Nie trzeba dodawać, vim $bacon
że nie będzie działać zgodnie z oczekiwaniami.
Co mogę zrobić, aby zdezynfekować tę ścieżkę bezwzględną, aby działała z innymi poleceniami?
command-line
bash
paths
Akiva
źródło
źródło
vim "$bacon"
Odpowiedzi:
Jak to zrobić poprawnie
Przede wszystkim zawsze podawaj swoje zmienne . To, co próbujesz zrobić, działa dobrze, jeśli odpowiednio go zacytujesz:
Zachowałem dziwną nazwę pliku, którą wybrałeś ( chociaż nie mam pojęcia, dlaczego ją wybrałeś ) dla zachowania spójności.
Teraz przypiszmy ścieżkę
pullingATerdon
do zmiennej, a następnie spróbuj otworzyć plik:To się nie powiedzie, zgodnie z oczekiwaniami. Ale jeśli teraz podamy to poprawnie:
Działa zgodnie z oczekiwaniami. I tak, możesz także otworzyć ścieżkę w (właściwym) edytorze:
emacs "$bacon"
będzie działać dobrze. OK, podobnie będzievim
i cokolwiek innego. Twój wybór redaktora, choć niefortunny, nie ma znaczenia.Dlaczego twój zawiódł
Szybkim sposobem na prześledzenie, co faktycznie się wydarzyło w twoim przypadku, jest użycie
set -x
(wyłączenie go ponownie za pomocąset +x
), co powoduje, że powłoka wypisuje każde polecenie, które uruchomi przed uruchomieniem. włącz komunikaty debugowania powłoki za pomocąset -x
:To pokazuje nam, że
ls
został uruchomiony z trzech oddzielnych argumenty'/home/terdon/foo/\e[92mM@r|<'
,'+'\''|'\''|_e|\|\|0rth'
i'[`-_-"]/pullingATerdon'
. Dzieje się tak, ponieważ powłoka wykonuje dzielenie słów i rozwijanie globu na ciągach niecytowanych. W tym przypadku problemem jest dzielenie słów, ponieważ powłoka widziała spacje na ścieżce i odczytywała każdy ciąg oddzielony spacją jako osobny argument.mkdir
Przykładem jest nieco inna, ale to dlatego, że jesteś pokazując nam się komunikat o błędzie z drugim wywołaniu polecenia. Wydaje mi się, że raz go wypróbowałeś, a następnie uruchomiłeś go po raz drugi, aby uzyskać wynik swojego pytania. Przy pierwszym uruchomieniu wyglądałby tak:Ponownie spróbuje utworzyć trzy katalogi, a nie jeden, z powodu podziału słów. Najpierw utworzył (z powodzeniem) katalog
/home/terdon/foo/\e[92mM@r|<
:Następnie również pomyślnie utworzył katalog o nazwie
+'|'|_e|\|\|0rth
w bieżącym katalogu:A następnie próbował utworzyć katalog
[`-_-"]/pullingATerdon
. Nie powiodło się, ponieważmkdir
domyślnie nie tworzy podkatalogów (może, jeśli go uruchomisz-p
):Ponieważ ciąg niecytowany zawierał
/
,mkdir
uważany za ścieżkę dwóch katalogów, próba znalezienia pierwszego i nie powiodła się.Dlatego się nie udało, ale to, co się stało, jest bardziej skomplikowane. Ciąg użyłeś jest rzeczywiście glob powłoki, konkretnie zakres glob , który pasuje do wszystkich plików w bieżącym katalogu, którego nazwa jest jednym z 5 znaków
`
,-
,_
lub"
. Ponieważ nie masz takich plików w bieżącym katalogu, glob nie pasuje do niczego i, podobnie jak domyślne zachowanie w bash, zwraca się:Aby to wyjaśnić, oto co się stanie, jeśli podasz glob, który pasuje do czegoś:
Niecytowany
[p*]
jest rozwijany do listy pasujących nazw plików (w tym przypadku tylko jednej) i do tego jest przekazywanyecho
. To kolejny powód, dla którego powinieneś cytować wszystkie rzeczy.Wreszcie rzeczywisty błąd, który wyświetlasz, pojawia się od drugiego uruchomienia polecenia i kończy się niepowodzeniem na pierwszym etapie podczas próby utworzenia
/home/terdon/foo/\e[92mM@r|<
, ponieważ poprzednie wywołanie utworzyło już ten katalog.Mówiąc bardziej ogólnie, za każdym razem, gdy pracujesz z dowolnymi nazwami plików, zawsze używaj globów powłoki. Takie rzeczy:
To zadziała dla dowolnej nazwy pliku. Bez względu na to, co się zawiera. W powyższym przykładzie mogłeś:
Wykona to każdy glob, który jednoznacznie identyfikuje plik docelowy. W ten sposób nie musisz się martwić o znaki specjalne i możesz po prostu pozwolić powłoce sobie z nimi poradzić.
Kilka przydatnych odniesień:
Jak mogę znaleźć i bezpiecznie obsługiwać nazwy plików zawierające znaki nowej linii, spacje lub oba? : Jedno z najczęściej zadawanych pytań na doskonałej Wiki Greya Cat.
Skutki bezpieczeństwa zapomnienia o cytowaniu zmiennej w powłokach bash / POSIX : ten sam post, do którego odwoływałem się na początku tej odpowiedzi. Świetne i bardzo szczegółowe wyjaśnienie wszystkich rzeczy, które mogą pójść nie tak, jeśli nie podasz poprawnie zmiennych zmiennych powłoki.
Dlaczego mój skrypt powłoki dusi się spacjami lub innymi znakami specjalnymi? : wszystko, co kiedykolwiek chciałeś wiedzieć o obsłudze dowolnych nazw plików w powłoce.
Kiedy konieczne jest podwójne cytowanie? : Więcej informacji o cudzysłowach i zmiennych, a szczególnie o kilku przypadkach, w których nie trzeba ich cytować
źródło