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
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.
find {directory} -type f -name '*.extension'
Beispielm alle CSV-Dateien im aktuellen Verzeichnis und seinen Unterverzeichnissen zu finden
find . -type f -name '*.csv'
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).
Ohne find
zu verwenden:
du -a $directory | awk '{print $2}' | grep '\.in$'
{
nach browsefolders ()
$in
sollten $suffix
seincut
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.
Um alle pom.xml
-Dateien in Ihrem aktuellen Verzeichnis zu finden und zu drucken, können Sie Folgendes verwenden:
find . -name 'pom.xml' -print
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.
find $directory -type f -name "*.in"|grep $substring
find "$PWD" -type f -name "*.in"
for file in "${LOCATION_VAR}"/*.Zip
do
echo "$file"
done