So finden/korrigieren Sie Fehler in einem Pfad

So finden/korrigieren Sie Fehler in einem Pfad

Es kommt häufig vor, dass ein langer Pfad falsch eingegeben wird oder Sie einen Protokolldateieintrag erhalten, dass ein Pfad nicht existiert. Gibt es einen Befehl oder eine Shell-Funktion, die durch die Pfadhierarchie navigiert, bis sie einen passenden Pfad findet?

Der Befehlszeilenaustausch könnte folgendermaßen ablaufen:

$ ls /var/lib/my/supper/complicated/path
File or directory not found
$ fixpath /var/lib/my/supper/complicated/path
Found /var/lib/my

Als Bonus-Feature wäre eine Ähnlichkeitserkennung toll:

$ fixpath /var/lib/my/supper/complicated/path
Found /var/lib/my
Did you mean /var/lib/my/super/complicated/path

Antwort1

 $ fixpath /home/user/docus/collection/unix/djakl/jfkdsl/dfjksld/fsdkl
Found /home/user/docus/collection/unix
 $ type fixpath
fixpath is a function
fixpath ()
{
    CURDIR="$PWD";
    DIR="$1";
    E=1;
    while [ $E -eq 1 ]; do
        cd "$DIR" 2> /dev/null && {
            E=0;
            echo Found "$DIR"
        } || {
            DIR="${DIR%/*}";
            DIR="${DIR:-/}"
        };
    done;
    cd "$CURDIR"
}

Die Ähnlichkeits-Autokorrektur können die meisten modernen Shells selbst durchführen. Zumindest Bash und Zsh können das.

Antwort2

Die folgende Shell-Funktion nimmt einen Pfadnamen und ermittelt das längste Stück davon, das tatsächlich existiert. Dies geschieht, indem das letzte Pfadelement aus dem Pfad entfernt wird, bis der Pfad entweder vollständig leer ist oder einer Datei (oder einem Verzeichnis oder irgendetwas) entspricht, die tatsächlich existiert.

fixpath () (
    pathname="$1"

    while [ -n "$pathname" ] && [ ! -e "$pathname" ]; do
        pathname=${pathname%/*}
        case "$pathname" in
            */*) continue ;;
            *) [ -e "$pathname" ] || pathname=''
               break
        esac
    done

    printf 'Longest existing path in "%s" is "%s"\n' "$1" "$pathname"
)

Die caseAnweisung wird benötigt, um die Schleife zu beenden, wenn $pathnamekein a enthalten ist /(was bedeutet, dass es durch die Variablensubstitution nicht verändert würde). Dadurch wird unter Umständen eine Endlosschleife vermieden.

Testen:

$ fixpath /home/kk/blaha/123
Longest existing path in "/home/kk/blaha/123" is "/home/kk"

$ fixpath "$HOME/.profile"
Longest existing path in "/home/kk/.profile" is "/home/kk/.profile"

$ fixpath "n"
Longest existing path in "n" is ""

verwandte Informationen