Welche Befehlszeile zum zuverlässigen Durchlaufen mehrerer Verzeichnisebenen

Welche Befehlszeile zum zuverlässigen Durchlaufen mehrerer Verzeichnisebenen

Ich habe das gleiche Problem wie in der Frage gestellt. Benennen Sie Musikdateien mit fehlenden Dateierweiterungen um und ich fand das von @Gilles bereitgestellte Skript sehr lehrreich, aber leider funktionierte es nicht so, wie ich es erwartet hatte. Was ich suchte, war ein Skript, das allen Musikdateien ohne Erweiterung in allen Unterverzeichnissen auf allen Ebenen unterhalb von "/Pfad/zum/Musikverzeichnis/" eine Dateierweiterung hinzufügt. Der vorgeschlagene Befehlszeilenparameter

/path/to/music/directory/{**/,}*

bewirkt, dass das Skript alle Dateien in den Unterverzeichnissen eine Ebene unter „/Pfad/zum/Musikverzeichnis/“ durchsucht, aber nicht die darunter liegenden Ebenen. Welchen Befehlszeilenparameter muss ich verwenden, um alle Dateien auf allen Ebenen unter „Verzeichnis/“ zu durchsuchen?

Wäre auch dankbar für einen Hinweis auf die Dokumentation für die

{**/,}* 

Teil.

Übrigens, für diejenigen, die an der ursprünglichen Antwort interessiert sind. Ich habe festgestellt, dass das Skript besser funktioniert, nachdem ich die Zeile geändert habe

file -i "$@" |

Zu

file --mime-type "$@" | 

(Wenn ich über die entsprechende Berechtigungsstufe verfügt hätte, hätte ich dies als Kommentar in der ursprünglichen Antwort angegeben.)

Antwort1

Ich denke, Sie müssen nur die Bash- globstarOption aktivieren, da diese standardmäßig nicht aktiviert ist inUbuntu, wie im Folgenden erläutert.

Der Ausdruck /path/to/music/directory/{**/,}*enthält zwei Erweiterungskonstrukte: eine Klammernerweiterung und als nächstes eine Pfadnamenerweiterung.

Klammererweiterung

Die Klammernerweiterung lässt sich am besten anhand eines Beispiels erklären:

$ printf '%s\n' before-{a,bb,1,22}-after
before-a-after
before-bb-after
before-1-after
before-22-after

(Ich habe hier und im Folgenden den Befehl verwendet, printf '%s\n' item1 item2 etc..der ähnlich ist echo, aber jedes Element in einer neuen Zeile druckt)

Sie sehen, dass jedes durch Kommas getrennte Element in Klammern ein erweitertes Element ergibt.

Das ursprüngliche Beispiel, das die Elemente **/und ein leeres Element in Klammern enthält, wird erweitert zu

$ printf '%s\n' /path/to/music/directory/{**/,}*
/path/to/music/directory/**/*
/path/to/music/directory/*

Globstar

Wenden wir uns nun dem Bash-Glob zu **, der zweimal imBash-Handbuchseite, beides in Bezug auf die Shell-Option globstar, und die Bedeutung ist wie folgt:

Das im Kontext einer Pfadnamenerweiterung verwendete Muster ** stimmt mit Dateien und null oder mehr Verzeichnissen und Unterverzeichnissen überein.

Diese Shell-Option ist nichtaktivstandardmäßig in Ubuntu:

$ shopt globstar
globstar        off

Sie können es aktivieren mit

shopt -s globstar

( shopt -u globstarmit deaktivieren).

Wenn wir die folgende Verzeichnisstruktur haben:

$ find first/ | sort
first/
first/aaa
first/second
first/second/bbb01
first/second/bbb02
first/second/third
first/second/third/ccc1
first/second/third/ccc2
first/second/third/ccc3

Wir könnten folgende Erweiterungen haben:

$ printf '%s\n' first/**/a*
first/aaa

$ printf '%s\n' first/**/b*
first/second/bbb01
first/second/bbb02

$ printf '%s\n' first/**/c*
first/second/third/ccc1
first/second/third/ccc2
first/second/third/ccc3

Sie sehen also, dass **es auf mehr als ein Pfadnamenelement erweitert werden kann.

Antwort2

Ich würde so etwas machen

#! /bin/bash

[[ -d "$1" ]] || { echo "$1 not a directory, exiting..."; exit 1; }

find "$1" -type f | while read F; do
  # do what you want with the "$F"
done

exit 0

und rufen Sie dann das Skript auf über./my_script <directory>

verwandte Informationen