Ausführen einer Bash-Funktion für jede mit dem Befehl „Find“ gefundene Datei

Ausführen einer Bash-Funktion für jede mit dem Befehl „Find“ gefundene Datei

Ich habe derzeit diesen Befehl, der jeden Dateinamen erfolgreich in einer eigenen Zeile ausgibt:

find . -exec echo {} \;

Ich versuche die Logik aufzuteilen, sodass der findBefehl eine Funktion ausführt. Basierend aufdiese FrageIch habe Folgendes versucht:

my_function() {
    echo $1
}
export -f my_function
find . -exec bash -c 'my_function "$@"' bash {} +

Dann bekomme ich diese Ausgabe:

.

Ich habe auch versucht, $@durch zu ersetzen $*, aber das führt dazu $1, dass jede einzelne Datei ohne Zeilenumbrüche ist. Ich möchte eine Logik ausführen, die jede Datei überprüft, also möchte ich immer $1nur eine Datei auf einmal. Ich habe versucht, die Ausgabe mit Leerzeichen durch aufzuteilen, for file in $1aber das funktioniert nicht für Dateien, die Leerzeichen im Dateinamen haben. Wie führe ich eine Bash-Funktion für jede vom findBefehl gefundene Datei aus?

BEARBEITEN: Hier ist das gesamte Skript, das ich verwende. Es scheint gut zu funktionieren.

# Ensures that non-csproj text files are formatted with LF line endings.
format() {
    for pathname do
        if [[ $pathname == *"git"* ]]; then
            continue
        elif [[ $pathname == *"csproj"* ]]; then
            continue
        fi
        dos2unix $pathname
    done
}
export -f format
find . -exec bash -c 'format "$@"' bash {} \;

Antwort1

Zum Ausführen dos2unix --newlineauf allen regulären Dateien im aktuellen Verzeichnis und darunter und Vermeiden aller Dateien, deren Name die Zeichenfolge enthält git:

find . -type f ! -name '*git*' -exec dos2unix --newline {} +

Das heißt, alle regulären Dateien suchen, deren Namen nicht mit dem Muster übereinstimmen , und alle in möglichst großen Batches gleichzeitig *git*ausführen . Ändern Sie es in , um alle Dateien zu vermeiden, deren Pfadname die Zeichenfolge enthält (z. B. Dateien in Verzeichnissen).dos2unix --newline! -name '*git*'! -path '*git*'git.git

Um explizit alle .gitVerzeichnisse zu vermeiden, aber alles andere einzuschließen, was gitim Namen enthalten sein könnte:

find . -name .git -prune -o -type f -exec dos2unix --newline {} +

Dadurch wird findsogar das Betreten eines Verzeichnisses verhindert, .gitindem -prunesolche Pfade aus dem Suchbaum gelöscht werden.


Antwort vor der Bearbeitung der Frage:

Ihre Funktion gibt nur ihr erstes Argument aus. Der Punkt ist der Suchpfad der obersten Ebene, den Sie mit verwenden find. Er wird übergeben, da Sie keine besondere Filterung der Verzeichniseinträge vornehmen (wie beispielsweise bei „ -type fNur für reguläre Dateien“, „oder -name“ oder einem anderen Testtyp find).

Wenn Sie möchten, dass Ihre Funktion alle Argumente ausgibt, verwenden Sie entweder

my_function() {
    printf '%s\n' "$@"
}

wodurch printfjedes Argument mit einer neuen Zeile dazwischen gedruckt wird, oder

my_function() {
    for pathname do
        printf '%s\n' "$pathname"
    done
}

das die Argumente durchläuft und printffür jedes einmal aufruft.

Dies würde ordnungsgemäß funktionieren, wenn Sie die Funktion wie folgt aufrufen würden:

my_function "$@"

aus Ihrem Inline- bash -cSkript heraus. Es "$@"wird auf alle dem Skript übergebenen Argumente erweitert, einzeln in Anführungszeichen gesetzt.

Eine andere Möglichkeit wäre, die Schleife in das bash -cSkript zu verschieben:

for pathname do
    my_function "$pathname"
done

und dann haben

my_function () {
    printf '%s\n' "$1"
}

Damit würden Sie explizit das tun, was Sie tun möchten, d. h. die Funktion einmal für jeden Pfadnamen aufrufen.

Der findBefehl würde dann entweder so aussehen:

find . -exec bash -c 'for pathname do my_function "$pathname"; done' bash {} +

oder, wohl etwas lesbarer,

find . -exec bash -c '
    for pathname do
        my_function "$pathname"
    done' bash {} +

Dies wäre übrigens dasselbe wie

shopt -s globstar nullglob dotglob

for pathname in ./**/*; do
    my_function "$pathname"
done

außer dass dies .nicht verarbeitet würde. Wenn Sie dies verwenden, müssen Sie Ihre my_functionFunktion nicht exportieren.

Mit der Schleife innerhalb der Funktion (wie in den ersten beiden Codeteilen dieser Antwort) würde dies verkürzt werden auf

shopt -s globstar nullglob dotglob

my_function ./**/*

verwandte Informationen