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?

-4voto

user Punkte 7158

Eine weitere Alternative besteht darin, keine Bash zu verwenden, sondern Python mit der Arbeit zu betrauen. Ich bin darauf zurückgekommen, weil Bash-Lösungen wie meine andere Antwort zu langsam waren.

Mit dieser Lösung erstellen wir ein Bash-Array von Dateien aus einem Inline-Python-Skript:

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

dsep=":"  # directory_separator
base_directory=/tmp

all_files=()
all_files_string="$(python3 -c '#!/usr/bin/env python3
import os
import sys

dsep="'"$dsep"'"
base_directory="'"$base_directory"'"

def log(*args, **kwargs):
    print(*args, file=sys.stderr, **kwargs)

def check_invalid_characther(file_path):
    for thing in ("\\", "\n"):
        if thing in file_path:
            raise RuntimeError(f"It is not allowed {thing} on \"{file_path}\"!")

def absolute_path_to_relative(base_directory, file_path):
    relative_path = os.path.commonprefix( [ base_directory, file_path ] )
    relative_path = os.path.normpath( file_path.replace( relative_path, "" ) )

    # if you use Windows Python, it accepts / instead of \\
    # if you have \ on your files names, rename them or comment this
    relative_path = relative_path.replace("\\", "/")
    if relative_path.startswith( "/" ):
        relative_path = relative_path[1:]
    return relative_path

for directory, directories, files in os.walk(base_directory):
    for file in files:
        local_file_path = os.path.join(directory, file)
        local_file_name = absolute_path_to_relative(base_directory, local_file_path)

        log(f"local_file_name {local_file_name}.")
        check_invalid_characther(local_file_name)
        print(f"{base_directory}{dsep}{local_file_name}")
' | dos2unix)";

if [[ -n "$all_files_string" ]];
then
    readarray -t temp <<< "$all_files_string";
    all_files+=("${temp[@]}");
fi;

for item in "${all_files[@]}";
do
    OLD_IFS="$IFS"; IFS="$dsep";
    read -r base_directory local_file_name <<< "$item"; IFS="$OLD_IFS";

    printf 'item "%s", base_directory "%s", local_file_name "%s".\n' \
            "$item" \
            "$base_directory" \
            "$local_file_name";
done;

Verwandt:

  1. os.walk ohne versteckte Verzeichnisse
  2. Wie kann man eine rekursive Unterordnersuche durchführen und Dateien in einer Liste zurückgeben?
  3. Wie teilt man eine Zeichenkette in ein Array in Bash?

-5voto

Wie wäre es, wenn Sie grep anstelle von find verwenden?

ls | grep .txt$ > out.txt

Jetzt können Sie diese Datei lesen, und die Dateinamen werden in Form einer Liste angezeigt.

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