2012-12-07 6 views
28

Ich habe eine Datei (sagen genannt list.txt), die relativen Pfade zu Dateien enthält, einen Pfad pro Zeile, also etwa so:Ubuntu bash script: Wie spalte ich den Weg nach dem letzten Schrägstrich?

foo/bar/file1 
foo/bar/baz/file2 
goo/file3 

Ich brauche einen Bash-Skript zu schreiben, die einen Pfad zu einer Zeit verarbeitet, teilt es beim letzten Schrägstrich und startet dann einen anderen Prozess, der die beiden Teile des Pfades als Argumente liefert. Bisher habe ich nur den Looping-Teil:

for p in `cat list.txt` 
do 
    # split $p like "foo/bar/file1" into "foo/bar/" as part1 and "file1" as part2 
    inner_process.sh $part1 $part2 
done 

Wie teile ich? Funktioniert das im entarteten Fall, wenn der Pfad keine Schrägstriche hat?

Thx

Antwort

65

Verwenden basename und dirname, das ist alles, was Sie brauchen.

part1=`dirname "$p"` 
part2=`basename "$p"` 
+0

Das ist eigentlich "part1 =' dirname $ p'/"da brauche ich den letzten Schrägstrich, aber ansonsten ist es perfekt :-) –

+3

Das wird kläglich zerbrechen, sobald ein Dateiname ein Leerzeichen oder lustige Symbole enthält .. . ':-(' –

+1

Ein solcher Bruch ist trivial zu lösen von Co urse: 'part1 =" $ (dirname "$ p") "' und 'part2 =" $ (basename "$ p") "' – zenaan

11

Eine richtige 100% bash Art und Weise und die in Bezug auf Dateinamen sicher ist, die Leerzeichen oder lustige Symbole haben (vorausgesetzt inner_process.sh behandelt sie richtig, aber das ist eine andere Geschichte):

while read -r p; do 
    [[ "$p" == */* ]] || p="./$p" 
    inner_process.sh "${p%/*}" "${p##*/}" 
done < list.txt 

und es funktioniert nicht Gabel dirname und basename (in Subshells) für jede Datei.

Die Zeile [[ "$p" == */* ]] || p="./$p" ist hier nur für den Fall $p enthält keinen Schrägstrich, dann fügt es ./ zu ihm hinzu.

Siehe Shell Parameter Expansion Abschnitt im Bash Reference Manual für weitere Informationen über die % und ## Symbole.

-3

Hier ist ein Beispiel zum Suchen und Ersetzen von Dateierweiterungen in XML.

for files in $(ls); do 

    filelist=$(echo $files |cut -f 1 -d "."); 
    mv $files $filelist.xml; 
done 
+4

Parsen Sie niemals ls. [Siehe hier, um zu erfahren, warum.] (Http://mywiki.wooled.org/ParsingLs) – XZS

2

Um zu @ gniourf_gniourf Kritik an der @ piokuc Antwort zu reagieren, während es kurz und einfach (wenn auch nicht so effizient) zu halten:

part1=`dirname "$p"` 
part2=`basename "$p"` 

(ich in einem Kommentar geantwortet haben würde, aber das ist syntaktisch nicht möglich.)

Verwandte Themen