2009-07-23 11 views
0

Ich habe einen Ordner, der eine ganze Reihe von Ordnern enthält, die jeweils eine Filmdatei enthalten. Jetzt möchte ich alle diese Filme auf einmal sehen können (aber ich muss die Ordnerstruktur beibehalten), also wollte ich sie alle mit dem obersten Ordner verknüpfen (flache Ansicht in Directory Opus wäre das Ziel, aber ich bin auf einem Mac). Hier ist mein VersuchShell-Skript, um bestimmte Dateien eine Ebene höher zu verknüpfen

for file in */*/*.mov; 
do 
newname='echo $file | sed "s|[^/]*/[^/]*/||g"'; 
ln -s $file echo $newname; 
done 

Also, was ich versuche, auf Linie zu tun, 3 drehen Sie den Pfad foo/bar/spud.mov in spud.mov und dann in Zeile 4 tun ln -s foo/bar/Spud .mov spud.mov

Aber es funktioniert nicht, alles, was ich bekommen ist

ln: "s | [^ /] /[^ /]/|| g": keine solche Datei oder Verzeichnis

I'v Ich habe verschiedene Kombinationen von Zitaten und Fluchten ausprobiert, aber ohne Glück. Der sed Ausdruck funktioniert, aber ich habe offensichtlich etwas mit meinen Variablen vermasselt.

Dank

Antwort

2

Was ist mit all dem Echo $ Datei | sed oder awk Zeug, wie auch immer? Basisname ist für diesen Zweck gemacht.

for file in */*/*.mov; do 
    newname=`basename $file1 
    ln -s $file $newname; 
done 

Aber wirklich, ln macht das Gleiche, wenn ein Verzeichnis angegeben, so:

for file in */*/*.mov; do 
    ln -s "$file" . 
done 

Oder eine wirklich Mehrzweck-Version, die nur auf Anruf ln so oft klug genug ist je nach Bedarf:

find . -name \*.mov -depth +1 -print0 | xargs -0 -J % ln -s % . 

das heißt, daß in dem lokalen Verzeichnis, findet alles mit einem Namen in .mov endet, die nicht im aktuellen Verzeichnis ist (Tiefe ist mehr als 1), trennen Sie die Ausgabe mit NULL-Werten und Rohr in xargs, das ist Suche nach NULL-separater Eingabe und wird übergeben. als das Argument zu ln nach all den Argumenten, die es auf stdin gelesen hat.

1

Basename ist, was Sie wollen, und das Problem mit Ihrer Lösung ist schlecht zu zitieren:

 
bash-3.2$ echo $file 
foo/bar/spud.mov 
bash-3.2$ newname=$(echo $file | sed 's|[^/]*/[^/]*/||g'); echo $newname 
spud.mov 
2

Dies wird für alle Ordner-Ebene das gleiche tun:


for i in `find . -name "*.mov"` 
do 
    file=`echo $i | /bin/awk -F'/' '{print $NF}'` 
    /bin/ln -s $i $file 
done 
+0

Der übliche Weg, um die letzte Komponente eines Pfadnamens zu erhalten, ist der Befehl basename: 'ln -s $ i $ (Basisname $ i)' –

+0

Es ist ok, den Basisnamen für eine von zwei Dateien zu verwenden. Verwenden der Shell-Interna-String-Funktionen, um "Basisname" zu erhalten, ist viel effizienter. – ghostdog74

+0

Sie brauchen keines von denen; gerade "." funktioniert, denn wenn ein Verzeichnis als letztes Argument übergeben wird, macht ln -s dasselbe ... – freiheit

0

Gut danke an alle. Scheint ein paar Würmer in dieser Dose zu sein. Es scheint, dass was ich getan habe, obwohl es nicht der beste Weg war, hätte funktioniert, wenn ich die richtige Syntax verwendet hätte.

Aber ich habe über Basisname gelernt und verbesserte mein Wissen über ln, so bin ich glücklich.

0

weiß, dass ich ein bisschen mehr darüber, wie zu bedienen, finden, so jetzt ich es in einer Zeile tun:

find . -name "*.mov" -exec ln -s {} \; 

die -exec Flag in dem Befehl find können Sie einen anderen Prozess laufen jedes Mal, es findet eine Datei. Fügen Sie wie oben beschrieben geschweifte Klammern ein, um die Datei als Parameter zu verarbeiten. Es dauerte eine Weile, bis ich herausgefunden habe, dass ein Leerzeichen vor dem gesperrten Semikolon stehen muss.