Jakie znaki należy wstawiać w plikach bez cudzysłowów?

12

Mam opartą na przeglądarce powłokę / terminal, który wykonuje polecenia bash i uciekam spacjami, ale okazuje się, że nawiasy również muszą być poprzedzone. Jakie inne znaki należy zmienić dla nazw plików, które nie są w cudzysłowach?

jcubic
źródło
Nie jest wcale jasne, co próbujesz zrobić. A co autouzupełnianie ma z tym wspólnego?
Michael Vehrs
@MichaelVehrs Mam polecenie mv filename filename-foow bash, które postacie muszę uciec, oprócz spacji i nawiasów?
jcubic
@MichaelVehrs usunął wzmiankę o autouzupełnianiu.
jcubic
Zasadniczo wszystkie metaznaki powłoki, takie jak białe spacje, globusy powłoki, zdarzenia historyczne. Z tego powodu należy przytoczyć całą nazwę pliku, zamiast ucieczki pojedynczych znaków: mv "$filename" "$newname".
Michael Vehrs
@MichaelVehrs Wiem, że cytowanie rozwiąże problem z ucieczką, ale muszę używać nazwy pliku bez cudzysłowów. Mam emulator terminala i powinien on działać, gdy użytkownik nie używa cudzysłowów.
jcubic

Odpowiedzi:

22

Prostym rozwiązaniem jest umieszczenie pojedynczego cudzysłowu ( ') na początku i innego pojedynczego cudzysłowu na końcu oraz zastąpienie każdego 'znaku w nazwie pliku sekwencją 4 znaków '\''. Wszystkie znaki tracą swoje specjalne znaczenie w ciągu pojedynczego cudzysłowu, z wyjątkiem 'siebie, która oznacza koniec łańcucha. Sekwencja '\''kończy dosłowny cytat, bezpośrednio po nim cytowany cytat i otwiera nowy literał cytowany. Zatem nazwa pliku

This file's name has some weird characters!
Will you manage to escape them?

można cytować w następujący sposób:

somecommand 'This file'\''s name has some weird characters!
Will you manage to escape them?'

Podwójne cudzysłowy mają bardziej złożone reguły ucieczki i nie pozwalają na dołączenie wykrzyknika, !jeśli aktywowane jest zastępowanie historii, więc nie będę ich więcej rozważał.

Alternatywnym podejściem jest ochrona znaków odwrotnym ukośnikiem. Działa to dla każdej postaci oprócz znaków nowej linii; w przypadku nowego wiersza umieszczenie go w pojedynczych cudzysłowach (lub podwójnych cudzysłowach) jest jedynym rozwiązaniem. Jeśli chcesz zminimalizować liczbę odwrotnych ukośników, aby przedstawić użytkownikowi cytowaną nazwę, możesz ograniczyć ją do miejsc, w których potrzebny jest odwrotny ukośnik; Jednak im więcej pomijasz ukośników odwrotnych, tym bardziej ryzykujesz, że zapomnisz jednego, który jest potrzebny. Litery, cyfry i znaki spoza ASCII są zawsze ok¹. Cytuj białe znaki i znaki interpunkcyjne, gdy nie masz pewności.

Przy typowej powłoce (ksh, bash lub zsh), musisz zacytować następujące znaki przynajmniej w niektórych okolicznościach.

  • Biała spacja (spacja, tabulator, nowa linia - pamiętając, że nowej linii nie można cytować za pomocą odwrotnego ukośnika).
  • ! - ekspansja historii.
  • " - składnia powłoki.
  • #- początek komentarza poprzedzony spacją; symbole wieloznaczne zsh.
  • $ - składnia powłoki.
  • & - składnia powłoki.
  • ' - składnia powłoki.
  • (- nawet w środku słowa: rozszerzone globs ksh (dostępne również w bash i zsh); symbole wieloznaczne zsh.
  • )(patrz ()
  • * - sh symbol wieloznaczny.
  • , - tylko wewnątrz rozszerzenia nawiasów klamrowych.
  • ; - składnia powłoki.
  • < - składnia powłoki.
  • = - w zsh, gdy jest na początku nazwy pliku (rozszerzenie nazwy pliku przy pomocy PATH).
  • > - składnia powłoki.
  • ? - sh symbol wieloznaczny.
  • [ - sh symbol wieloznaczny.
  • \ - składnia powłoki.
  • ] - możesz uciec od pozostawienia go bez cudzysłowu.
  • ^- ekspansja historii; Zsh wildcard.
  • ` - składnia powłoki.
  • { - rozszerzenie nawiasów klamrowych.
  • | - składnia powłoki.
  • } - należy uciec w Zsh, inne pociski są bardziej łagodne, gdy nie ma pasującego otwierającego nawiasu klamrowego.
  • ~- rozszerzenie katalogu domowego, gdy jest na początku nazwy pliku; znak zsh; zawsze bezpieczny, gdy jest to ostatnia postać.

Kilka dodatkowych postaci może czasem wymagać specjalnego postępowania:

  • -nie jest specjalny dla powłoki, ale gdy jest na początku argumentu polecenia, wskazuje opcję. Nie można go chronić cudzysłowami, ponieważ specjalna obsługa znajduje się w poleceniu, a nie w powłoce. Aby zabezpieczyć nazwę pliku, która zaczyna się od -, możesz wstawić ./przed nią - w ten sposób jest to nadal ten sam plik, ale argument już się nie zaczyna -.
  • .sam w sobie nie jest wyjątkowy, ale pliki kropek są *domyślnie wyłączone z globusów.
  • :nie jest specjalny dla powłoki, ale niektóre polecenia analizują ją specjalnie, np. aby wskazać plik zdalny ( hostname:filename). Zapoznaj się z dokumentacją polecenia, aby dowiedzieć się, jak radzić sobie z nazwami plików zawierającymi dwukropki.

¹ Chyba że użytkownik skonfigurował alternatywne znaki rozszerzenia historii. Niektóre powłoki na to pozwalają. To kolejny powód, aby używać pojedynczych cudzysłowów zamiast odwrotnych ukośników.

Gilles „SO- przestań być zły”
źródło
Newlines, przynajmniej LFtylko, mogą być cytowane z ukośnikiem odwrotnym w niektórych powłokach.
iBug
@ iBug Nie. W dowolnej powłoce typu shslash + nowa linia rozwija się do pustego ciągu, a nie do nowej linii.
Gilles „SO- przestań być zły”
To dobra odpowiedź, dziękuję. Czy istnieje link do miejsca, w którym te informacje są „oficjalnie” dostępne?
slashmais,
1
@slashmais Jakie informacje? Składnia języka powłoki jest „oficjalnie” dostępna w różnych instrukcjach i specyfikacjach, ale od tego momentu, aby dowiedzieć się, które znaki wymagają cytowania, nie jest całkowicie proste.
Gilles 'SO - przestań być zły'
1
Znalazłem też: tecmint.com/manage-linux-filenames-with-special-characters - nie jest tak zwarty jak twoja lista, ale ma wiele przykładów. (by-by-by: „Jakie informacje?” nie jest fajną odpowiedzią, gdy temat dotyczy postaci)
slashmais