428 Stimmen

Wie kann man eine Schleife durch die von find zurückgegebenen Dateinamen ziehen?

x=$(find . -name "*.txt")
echo $x

Wenn ich den obigen Code in der Bash-Shell ausführe, erhalte ich eine Zeichenkette mit mehreren durch Leerzeichen getrennten Dateinamen, keine Liste.

Natürlich kann ich sie weiter nach Leerzeichen trennen, um eine Liste zu erhalten, aber ich bin sicher, dass es einen besseren Weg gibt, dies zu tun.

Wie kann man also am besten eine Schleife durch die Ergebnisse einer find Befehl?

9voto

Celuk Punkte 192

Ich denke, mit diesem Codestück (Einfügen des Befehls nach while done ):

while read fname; do
  echo "$fname"
done <<< "$(find . -name "*.txt")"

ist besser als diese Antwort denn while Schleife wird in einer Subshell ausgeführt, und zwar gemäß aquí , wenn Sie diese Antwort und variable Änderungen sind nicht mehr erkennbar, nachdem while Schleife, wenn Sie Variablen innerhalb der Schleife ändern wollen.

8voto

Seppo Enarvi Punkte 2830

Wenn Sie davon ausgehen können, dass die Dateinamen keine Zeilenumbrüche enthalten, können Sie die Ausgabe von find mit folgendem Befehl in ein Bash-Array:

readarray -t x < <(find . -name '*.txt')

Anmerkung:

  • -t verursacht readarray um Zeilenumbrüche zu entfernen.
  • Es wird nicht funktionieren, wenn readarray befindet sich in einer Rohrleitung, daher die Prozesssubstitution.
  • readarray ist seit Bash 4 verfügbar.

Bash 4.4 und höher unterstützt auch die -d zur Angabe des Begrenzungszeichens. Die Verwendung des Null-Zeichens anstelle eines Zeilenumbruchs zur Abgrenzung der Dateinamen funktioniert auch in dem seltenen Fall, dass die Dateinamen Zeilenumbrüche enthalten:

readarray -d '' x < <(find . -name '*.txt' -print0)

readarray kann auch aufgerufen werden als mapfile mit den gleichen Optionen.

Referenz: https://mywiki.wooledge.org/BashFAQ/005#Loading_lines_from_a_file_or_stream

6voto

bmargulies Punkte 94152
# Doesn't handle whitespace
for x in `find . -name "*.txt" -print`; do
  process_one $x
done

or

# Handles whitespace and newlines
find . -name "*.txt" -print0 | xargs -0 -n 1 process_one

4voto

Paco Punkte 131

Ich verwende gerne find, das zuerst einer Variablen zugewiesen wird und IFS, das in eine neue Zeile geschaltet wird, wie folgt:

FilesFound=$(find . -name "*.txt")

IFSbkp="$IFS"
IFS=$'\n'
counter=1;
for file in $FilesFound; do
    echo "${counter}: ${file}"
    let counter++;
done
IFS="$IFSbkp"

Wie von @Konrad Rudolph kommentiert, funktioniert dies nicht mit "neuen Zeilen" im Dateinamen. Ich denke, es ist immer noch praktisch, da es die meisten Fälle abdeckt, in denen man eine Schleife über die Befehlsausgabe machen muss.

4voto

user Punkte 7158

Wie bereits in der oberen Antwort von Kevin Die beste Lösung ist die Verwendung einer for-Schleife mit bash glob, aber da bash glob standardmäßig nicht rekursiv ist, kann dies durch eine rekursive bash-Funktion behoben werden:

#!/bin/bash
set -x
set -eu -o pipefail

all_files=();

function get_all_the_files()
{
    directory="$1";
    for item in "$directory"/* "$directory"/.[^.]*;
    do
        if [[ -d "$item" ]];
        then
            get_all_the_files "$item";
        else
            all_files+=("$item");
        fi;
    done;
}

get_all_the_files "/tmp";

for file_path in "${all_files[@]}"
do
    printf 'My file is "%s"\n' "$file_path";
done;

Verwandte Fragen:

  1. Bash-Schleife durch Verzeichnis einschließlich versteckter Datei
  2. Rekursive Auflistung von Dateien aus einem bestimmten Verzeichnis in der Bash
  3. ls-Befehl: Wie erhalte ich eine rekursive Auflistung des gesamten Pfads, eine Zeile pro Datei?
  4. Dateien rekursiv in Linux CLI mit Pfad relativ zum aktuellen Verzeichnis auflisten
  5. Rekursiv alle Verzeichnisse und Dateien auflisten
  6. Bash-Skript, Array mit allen Dateien in einem Verzeichnis erstellen
  7. Wie kann ich ein Array erstellen, das die Namen aller Dateien in einem Ordner enthält?
  8. Wie kann ich ein Array erstellen, das die Namen aller Dateien in einem Ordner enthält?
  9. Wie erhält man die Liste der Dateien in einem Verzeichnis in einem Shell-Skript?

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X