find . -iname "*.sh" -exec basename {} \; | sed s/\.sh//g
Das basename
Dienstprogramm entfernt alle Verzeichnisinformationen aus einem Pfad - relativ oder absolut.
Das dirname
Dienstprogramm führt bei Bedarf das Gegenteil aus.
find . -iname "*.sh" | sed 's/[.]sh$//' ./backup/samukano/ex04/who_am_i ./backup/samukano/ex05/people ./days/day01/samukano/ex01/print_groups ./days/day01/samukano/ex02/find_sh ./samukano/ex04/who_am_i ./samukano/ex05/people
Und ich brauche nur
who_am_i people ... people
find . -iname "*.sh" -exec basename {} \; | sed s/\.sh//g
Das basename
Dienstprogramm entfernt alle Verzeichnisinformationen aus einem Pfad - relativ oder absolut.
Das dirname
Dienstprogramm führt bei Bedarf das Gegenteil aus.
Tragbar, nicht robust:
find . -type f \( -name "*.sh" -o -name "*.Sh" -o -name "*.sH" -o -name "*.SH" \) | sed -e 's|^.*/||' -e 's/[.][sS][hH]$//'
Robust, zum Analysieren als nullterminierte Zeichenfolgen:
find . -type f -iname "*.sh" -printf "%f\0" | sed -z 's/[.][sS][hH]$//'
Intern robust mit möglicherweise mehrdeutiger Ausgabe zum Anzeigen:
find . -type f -iname "*.sh" -printf "%f\0" | sed -z 's/[.][sS][hH]$/\n/'
Es gibt viele Möglichkeiten, einige robuster als andere. Außerdem verfügen die Tools, die Sie verwenden möchten, überlappende Funktionen. Viele davon sind jedoch nicht POSIX-fähig, sodass Sie möglicherweise nicht über die erforderlichen Optionen verfügen.
Außerdem kann jedes Verzeichnis des Dateinamens Zeilenumbrüche und andere merkwürdige Zeichen enthalten. Um Dateinamen auf eine robuste Weise zu analysieren, möchten Sie sie als nullterminierte Zeichenfolgen behandeln.
Dann möchten Sie das Ergebnis ohnehin mit Zeilenumbrüchen (dh regulären Strings) drucken, um die Lesbarkeit zu gewährleisten (allerdings besteht die Gefahr einer mehrdeutigen Ausgabe).
Werkzeuge unterstützen normalerweise nullterminierte Zeichenfolgen mit Nicht-POSIX-Erweiterungen.
Um beispielsweise diese vollständigen Pfade, die das Hauptproblem darstellen, loszuwerden, können Sie Folgendes verwenden:
find . -printf "%f"
, aber Ihr find
kann oder kann nicht unterstützen -printf
;basename
;sed
.Zum Abisolieren können .sh
Sie verwenden:
basename path_to_process .sh
, aber die Groß- und Kleinschreibung wird berücksichtigt, und ich denke, dass Sie -iname
aus einem bestimmten Grund verwendet wurden (Hinweis -iname
ist für POSIX nicht erforderlich);sed
(wie Sie es getan haben), wobei die Groß- und Kleinschreibung nicht beachtet werden kann.Diese Analyse ist nicht erschöpfend.
Die robusteste Version ohne Berücksichtigung von Groß- und Kleinschreibung gibt nullterminierte Zeichenfolgen zurück. Dies macht die Ausgabe für die weitere Analyse absolut zuverlässig:
find . -type f -iname "*.sh" -printf "%f\0" | sed -z 's/[.][sS][hH]$//'
Dasselbe Ergebnis, das von Menschen lesbar und möglicherweise mehrdeutig ist:
find . -type f -iname "*.sh" -printf "%f\0" | sed -z 's/[.][sS][hH]$/\n/'
Die Mehrdeutigkeit manifestiert sich so:
foo bar
Gab es zwei Skripte: foo.sh
und bar.sh
? oder nur einer foo(newline here)bar.sh
?
Es wird noch verwirrender, wenn Sie nicht verwenden können sed -z
und müssen Input liefern sed
als Newline-terminierten Strings. In diesem Fall foo.sh(newline here)bar.sh
generiert eine einzelne Datei auch die obige Ausgabe.
Was passiert, wenn Ihr sed
Träger -z
aber find
nicht unterstützt -printf
? Vielleicht ist Ihr basename
Träger -z
. Dies sollte völlig robust sein:
find . -type f -iname "*.sh" -exec basename -z -a {} + | sed -z 's/[.][sS][hH]$//'
oder ohne die Unterstützung für -a
:
find . -type f -iname "*.sh" -exec basename -z {} \; | sed -z 's/[.][sS][hH]$//'
Ich kann sehen, dass Ihr find
Support unterstützt -iname
, es kann jedoch nicht sein. Was wäre, wenn es nicht wäre? Ganz naiver aber funktionierender Ansatz:
find . -type f \( -name "*.sh" -o -name "*.Sh" -o -name "*.sH" -o -name "*.SH" \) ...
Wie Sie sehen, hängt alles von den verfügbaren Optionen ab.
Angenommen, Ihre Pfade verwenden einen sicheren Satz druckbarer Zeichen (keine Zeilenumbrüche usw.). Dieser Befehl sollte tragbar und gut genug sein:
find . -type f \( -name "*.sh" -o -name "*.Sh" -o -name "*.sH" -o -name "*.SH" \) | sed -e 's|^.*/||' -e 's/[.][sS][hH]$//'