Szukam eleganckiej jednowarstwowej (np. awk
), Która skróci ciąg ścieżki uniksowej, używając pierwszego znaku każdego poziomu nadrzędnego / pośredniego, ale pełnej nazwy basename. Łatwiej jest pokazać za pomocą przykładów:
/path/to/file
→/p/t/file
/tmp
→/tmp
/foo/bar/.config/wizard_magic
→/f/b/./wizard_magic
/foo/bar/.config/wizard_magic
→/f/b/.c/wizard_magic
W świetle dobrych punktów @ MichaelKjörling i @ChrisH poniżej, ten przykład pokazuje, w jaki sposób możemy pokazać pierwsze dwa znaki, gdy pierwszy znak jest kropką.
/f/b/.c/wizard_magic
. Kropka jest często tak powszechna w danym katalogu, że stanowi bardzo małą wskazówkę, gdzie należy szukać..
zwykle oznacza po prostu „bieżący katalog”. Tak/f/b/./wizard_magic
samo jest,/f/b/wizard_magic
ponieważ element ścieżki./
kompresuje się do pustego elementu ścieżki.Odpowiedzi:
Dla tego pliku testowego:
Skróty można wygenerować za pomocą tego kodu awk:
Edycja1: Używanie dwóch znaków dla nazw kropek
Ta wersja skraca nazwy katalogów do jednego znaku, z wyjątkiem nazw rozpoczynających się,
.
które są skracane do dwóch znaków:Jak to działa
-F/
To mówi awk, aby używał ukośnika jako separatora pól na wejściu.
for (i=1;i<NF;i++) $i=substr($i,1,1)
Zapętla się ono nad każdym polem, z wyjątkiem ostatniego, i zastępuje je tylko pierwszym znakiem.
EDYCJA 1: W poprawionej wersji określamy długość podciągu 2, gdy pole zaczyna się od
.
.1
To każe awk wydrukować zmienioną linię.
OFS=/
To mówi awk, aby używał ukośnika jako separatora pól na wyjściu.
źródło
‥
separatora:awk -F/ '{for (i=1;i<NF;i++) $i=substr($i,1,1+($i~/^[.]/))(i==1||length($i)<2?"":"‥")} 1' OFS=/ <<<$PWD
daje:/foo/bar/.config/wizard_magic
→/f‥/b‥/.c‥/wizard_magic
Całkiem łatwe w sed (zakładając, że w nazwach plików nie ma nowych linii):
W awk jest to mniej łatwe, ponieważ brakuje w nim odwołań wstecznych (z wyjątkiem Gawk, ale z niezdarną składnią):
W zsh (ze ścieżką w
$full_path
):źródło
\1
w ciągu zastępowania ma oznaczać odniesienie do grupy przechwytywania w strukturze. Odsyłacz zwrotny to odsyłacz zwrotny bez względu na to, gdzie go używasz.możesz to zrobić w następujący sposób:
a oto
sed
:co jest prawie bliskie zrobieniu wszystkich tych samych czynności, które wykonuje funkcja poniżej. nie tworzy skrótów z tyldami ani nie wstawia
$PWD
do głowy wiodącego nie-ukośnika, jak robi to funkcja (i w rzeczywistości nigdy nie drukuje początkowego ukośnika), ale można to później obsłużyć. przetwarza komponenty ścieżki zerowej i pojedynczych kropek oraz odsuwa..
przypadki.podana ta sama
man
ścieżka, jakcd
powyżej, drukuje:wypisze również jedną lub dwie dodatkowe kropki wiodące dla każdego komponentu ścieżki, który zaczyna się od takiego i nie jest tylko jedną lub dwiema kropkami.
poprosiłeś o zrobienie więcej niż jednego znaku dla komponentu ścieżki zaczynającego się na
.
. do tego doszedłem do wniosku, że każdy komponent i tak wymaga indywidualnej uwagi, a ponieważ byłem ciekawy, spróbowałem wypracować kanoniczną ścieżkę bez katalogu zmian. po kilku próbach i błędach ostatecznie zdecydowałem, że jedynym sposobem na zrobienie tego dobrze jest zrobienie tego dwa razy - wstecz i do przodu:tak, że nigdy nie zmienia katalogu ani nie próbuje potwierdzić istnienia żadnego komponentu ścieżki, ale ściska powtarzające się
/
separatory i/./
całkowicie usuwa komponenty pojedynczej kropki i odpowiednio przetwarza/../
komponenty podwójnej kropki.gdy
$IFS
jest ustawiony na jakiś znak inny niż biały , sekwencja dwóch lub więcej$IFS
znaków spowoduje jedno lub więcej pustych pól. więc wiele kolejnych ukośników działa na argumenty o wartości zerowej. to samo dotyczy wiodącej$IFS
postaci. a więc kiedyset -- $1
dzieli, jeśli wynik$1
jest pusty, to zaczyna się od ukośnika, w przeciwnym${1:+$PWD}
razie , jeśli nie jest pusty, wstawiam$PWD
. innymi słowy, jeśli pierwszy argument nie zaczyna się od ukośnika, zostanie$PWD
dodany. jest to tak bliskie, jak w przypadku sprawdzania poprawności ścieżki .w przeciwnym razie pierwsza
for
pętla rekurencyjnie odwraca kolejność składników ścieżki, takich jak:... robiąc to, ignoruje komponenty jednopunktowe lub zerowe, i
..
robi to ...... drugie przejście odwraca ten efekt i jednocześnie ściska każdy składnik do 2 kropek + char lub 1-kropka + char lub char .
więc powinno dojść do kanonicznej ścieżki niezależnie od istnienia.
dodałem / odjąłem trochę do drugiej pętli. jest teraz
set
rzadziej (tylko raz dla każdego[!./]*
komponentu) i przezcase
większość czasu ocenia wzorce zwarć (dzięki wyżej wspomnianemu wzorowi) i obejmuje ocenę dopasowania przywołania ogona~
. jeśli całość lub część wiodąca (podzielona na całe komponenty) ostatecznie kanonicznej ścieżki mogą się zgadzać~
, pasujący bit zostanie usunięty i literał~
zostanie zastąpiony. aby to zrobić, musiałem również zachować pełną kopię ścieżki obok skróconej (ponieważ dopasowanie skróconej ścieżki do~
prawdopodobnie nie byłoby bardzo pomocne) , więc jest to przechowywane$3
. ostatniwhile
gałąź pętli jest uruchamiana tylko wtedy, gdy~
jest dopasowana jako podzbiór$3
.jeśli uruchomisz go z
set -x
włączonym śledzeniem, możesz zobaczyć, jak działa.źródło
„Podejrzany” zsh motyw z Oh My zsh zawiera Perl snippet właśnie do tego, że ma wsparcie Unicode:
źródło
Czy chcesz mieć krótką nazwę lub używać jej w wierszu poleceń?
W przypadku wiersza polecenia mam następujące sugestie:
Czy uzupełnianie plików w powłoce nie pomaga?
Czasami masz szczęście i nie musisz robić czegoś specjalnego:
Gdy masz tylko niektóre katalogi, którymi jesteś zainteresowany, możesz użyć aliasów:
Lub możesz ustawić zmienne dla swoich ulubionych katalogów
Myślę, że te opcje mają większy sens niż próba rozwiązania tego za pomocą funkcji zdefiniowanej w .bashrc (lub .profile), takich jak
i wywoływanie tej funkcji x ze spacjami między twoimi literami:
źródło