it-swarm.com.de

Suchen Sie rekursiv nach Dateien mit einer bestimmten Erweiterung

Ich versuche, alle Dateien mit einer bestimmten Erweiterung in einem Verzeichnis und seinen Unterverzeichnissen mit meiner Bash zu finden (neueste Ubuntu LTS-Version).

Folgendes steht in einer Skriptdatei:

#!/bin/bash

directory="/home/flip/Desktop"
suffix="in"

browsefolders ()
  for i in "$1"/*; 
  do
    echo "dir :$directory"
    echo "filename: $i"
    #   echo ${i#*.}
    extension=`echo "$i" | cut -d'.' -f2`
    echo "Erweiterung $extension"
    if     [ -f "$i" ]; then        

        if [ $extension == $suffix ]; then
            echo "$i ends with $in"

        else
            echo "$i does NOT end with $in"
        fi
    Elif [ -d "$i" ]; then  
    browsefolders "$i"
    fi
  done
}
browsefolders  "$directory"

Wenn ich dieses Skript im Terminal starte, heißt es leider:

[: 29: in: unexpected operator

(mit $extension anstelle von 'in')

Was ist hier los, wo ist der Fehler? Aber diese geschweifte Klammer

382
flip
find $directory -type f -name "*.in"

ist ein bisschen kürzer als das Ganze (und sicherer - befasst sich mit Leerzeichen in Dateinamen und Verzeichnisnamen).

Ihr Skript schlägt wahrscheinlich bei Einträgen fehl, deren Name kein . enthält, wodurch $extension leer wird.

678
Mat
find {directory} -type f -name '*.extension'

Beispielm alle CSV-Dateien im aktuellen Verzeichnis und seinen Unterverzeichnissen zu finden

find . -type f -name '*.csv'
158

Die Syntax, die ich verwende, unterscheidet sich ein wenig von der von @Matt vorgeschlagenen:

find $directory -type f -name \*.in

(Es ist ein Tastendruck weniger).

58
Scott C Wilson

Ohne find zu verwenden:

du -a $directory | awk '{print $2}' | grep '\.in$'
12
rtrn
  1. Es fehlt ein { nach browsefolders ()
  2. Alle $in sollten $suffix sein
  3. Die Zeile mit cut enthält nur den mittleren Teil von front.middle.extension. Sie sollten Ihr Shell-Handbuch auf ${varname%%pattern} und Freunden nachlesen.

Ich gehe davon aus, dass Sie dies als Übung in Shell-Skripten durchführen, andernfalls ist die bereits vorgeschlagene find -Lösung der richtige Weg.

Verwenden Sie sh -n scriptname, um die korrekte Shell-Syntax zu überprüfen, ohne ein Skript auszuführen.

10
Jens

Um alle pom.xml -Dateien in Ihrem aktuellen Verzeichnis zu finden und zu drucken, können Sie Folgendes verwenden:

find . -name 'pom.xml' -print
6
Bharat Yadav

Obwohl die Verwendung des Befehls find hier nützlich sein kann, bietet die Shell selbst Optionen, um diese Anforderung ohne Tools von Drittanbietern zu erfüllen. Die bash -Shell bietet eine erweiterte Glob-Support-Option, mit der Sie die Dateinamen unter rekursiven Pfaden abrufen können, die mit den gewünschten Erweiterungen übereinstimmen.

Die erweiterte Option ist extglob, die mit der unten stehenden Option shopt festgelegt werden muss. Die Optionen werden mit der Unterstützung von -s aktiviert und mit dem Flag -u deaktiviert. Zusätzlich könnten Sie einige Optionen verwenden, d. H. nullglob, bei denen ein nicht übereinstimmender Glob vollständig weggefegt und durch einen Satz von Nullwörtern ersetzt wird. Und globstar, mit dem alle Verzeichnisse durchsucht werden können

shopt -s extglob nullglob globstar

Jetzt müssen Sie nur noch den Glob-Ausdruck bilden, um die Dateien einer bestimmten Erweiterung einzuschließen. Dies können Sie wie folgt tun. Wir verwenden ein Array, um die Glob-Ergebnisse zu füllen, da die Dateinamen mit Sonderzeichen bei korrekter Anführungszeichen- und Erweiterungsangabe intakt bleiben und nicht durch das Aufteilen von Wörtern durch die Shell beschädigt werden.

Zum Beispiel, um alle *.csv -Dateien in den rekursiven Pfaden aufzulisten

fileList=(**/*.csv)

Mit der Option ** können Sie die Unterordner erneut durchsuchen, und *.csv ist eine globale Erweiterung, die alle Dateien mit den genannten Erweiterungen enthält. Jetzt zum Drucken der eigentlichen Dateien einfach machen

printf '%s\n' "${fileList[@]}"

Die Verwendung eines Arrays und eine korrekte Erweiterung in Anführungszeichen ist die richtige Methode, wenn Sie in Shell-Skripten verwendet werden. Für die interaktive Verwendung können Sie jedoch einfach ls mit dem Glob-Ausdruck as verwenden

ls -1 -- **/*.csv

Dies könnte sehr gut erweitert werden, um mehreren Dateien zu entsprechen, d. H. Dateien, die mit mehreren Erweiterungen enden (d. H. Ähnlich dem Hinzufügen mehrerer Flags im find -Befehl). Angenommen, Sie müssen nur alle rekursiven Bilddateien abrufen, d. H. Die Erweiterungen *.gif, *.png und *.jpg

ls -1 -- **/+(*.jpg|*.gif|*.png)

Dies könnte sehr gut erweitert werden, um auch negative Ergebnisse zu erzielen. Mit der gleichen Syntax könnte man die Ergebnisse des Globus verwenden, um Dateien eines bestimmten Typs auszuschließen. Angenommen, Sie möchten Dateinamen mit den obigen Erweiterungen ausschließen, dann könnten Sie dies tun

excludeResults=()
excludeResults=(**/!(*.jpg|*.gif|*.png))
printf '%s\n' "${excludeResults[@]}"

Das Konstrukt !() ist eine Negationsoperation, bei der keine der darin aufgeführten Dateierweiterungen enthalten ist, und | ist ein Alternationsoperator, wie er in der Extended Regular Expressions-Bibliothek zum Ausführen eines OR verwendet wird. Spiel der Tropfen.

Beachten Sie, dass diese erweiterte Glob-Unterstützung in der POSIX bourne-Shell nicht verfügbar ist und nur für aktuelle Versionen von bash gilt. Wenn Sie also die Portabilität der Skripte in Betracht ziehen, die auf POSIX- und bash -Shells ausgeführt werden, ist diese Option nicht richtig.

4
Inian
find $directory -type f -name "*.in"|grep $substring
1
Sergiu
find "$PWD" -type f -name "*.in"
1
kip2
for file in "${LOCATION_VAR}"/*.Zip
do
  echo "$file"
done