• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

[Gelöst] bash-Script, um viele Dateien automatisch zu verlinken

Christina

Moderator
Teammitglied
Hi,

könnte mir bitte jemand helfen, eine Kommandozeile oder ein kleines bash-Script zu erstellen?
Ich möchte alle Audio-Dateien in einem Verzeichnis nach einem anderen Song-Namen verlinken.
z.B.:
Code:
ls
01. 9 To 5.wav                                     11. Potential New Boyfriend.wav
02. I Will Always Love You [Original Version].wav  12. Everything's Beautiful (In It's Own Way).wav
03. Islands In The Stream.wav                      13. Silver Threads And Golden Needles.wav
04. Jolene.wav                                     14. To Know Him Is To Love Him.wav
05. Coat Of Many Colors.wav                        15. Why'd You Come In Here Lookin' Like That.wav
06. My Tennessee Mountain Home.wav                 16. Romeo.wav
07. Here You Come Again.wav                        17. Tennessee Homesick Blues.wav
08. Baby I'm Burning.wav                           18. Dumb Blonde.wav
09. Love Is Like A Butterfly.wav                   19. Applejack.wav
10. The Bargain Store.wav                          20. Old Flames Can't Hold A Candle To You.wav
„von Hand verlinkt“
Code:
ln 01.\ 9\ To\ 6.flac Dolly\ Parton-The\ Very\ Best\ Of-01.flac
…
ln 20.\ Old\ Flames\ Can't\ Hold A\ Candle\ To\ You.flac Dolly\ Parton-The\ Very\ Best\ Of-20.flac
Die Hard-Links möchte ich automatisch erstellen lassen und nur den Basisnamen (z.B. Dolly Parton-The Very Best Of) und die Dateiendung (z.B. .flac) eintippen / abändern müssen. Das Hochzählen von „-01“ an soll auch automatisch erfolgen und am Link zwischen dem Basisnamen und der Dateiendung eingefügt werden.

Vielleicht lässt sich das sogar über eine einzige lange Kommandozeile lösen, die ich dann immer als Vorlage nehme, aber da fehlen mir leider noch die tieferen bash-Kenntnisse.
Für jede Hilfe bin ich dankbar! :)
lg Christina
 

abgdf

Guru
Code:
ln 01.\ 9\ To\ 6.flac Dolly\ Parton-The\ Very\ Best\ Of-01.flac
Code:
ln: Die harte Verknüpfung ...  konnte nicht angelegt werden: Die Datei existiert bereits.
Kann es sein, daß Du eine unrichtige Vorstellung davon hast, was Links im Sinne von "ln" sind?

Beschreib' doch bitte nochmal abstrakt, was Du machen möchtest, bzw. warum Du Links auf diese Audio-Dateien haben möchtest.
 
OP
Christina

Christina

Moderator
Teammitglied
Also, bei mir funktioniert das:
Zuerst
Code:
parallel flac -8 {} ::: *.wav
dann
Code:
$ ln 01.\ 9\ To\ 5.flac Dolly\ Parton-The\ Very\ Best\ Of-01.flac
$ ls -i
2482178 01. 9 To 5.flac                                     2482189 12. Everything's Beautiful (In It's Own Way).flac
2482179 02. I Will Always Love You [Original Version].flac  2482190 13. Silver Threads And Golden Needles.flac
2482180 03. Islands In The Stream.flac                      2482191 14. To Know Him Is To Love Him.flac
2482181 04. Jolene.flac                                     2482192 15. Why'd You Come In Here Lookin' Like That.flac
2482182 05. Coat Of Many Colors.flac                        2482193 16. Romeo.flac
2482183 06. My Tennessee Mountain Home.flac                 2482194 17. Tennessee Homesick Blues.flac
2482184 07. Here You Come Again.flac                        2482195 18. Dumb Blonde.flac
2482185 08. Baby I'm Burning.flac                           2482196 19. Applejack.flac
2482186 09. Love Is Like A Butterfly.flac                   2482197 20. Old Flames Can't Hold A Candle To You.flac
2482187 10. The Bargain Store.flac                          2482178 Dolly Parton-The Very Best Of-01.flac
2482188 11. Potential New Boyfriend.flac
$ find /home/ -inum 2482178 -print
/home/public/Dolly Parton/Dolly Parton-The Very Best Of-01.flac
/home/public/Dolly Parton/01. 9 To 5.flac
Ich möchte einfach Songs von Interpreten/-innen noch in einem ganz anderen Verzeichnis (auf der selben Partition) nur mit dem Albumnamen haben, ohne dass ich den doppelten Speicherplatz benötige.
 

manzek

Hacker
Normalerweise arbeiten die meisten Wiedergabeprogramme mit Playlists, was ja letztendlich auch nichts anderes ist, als ein Link zu der Musik.
Deutlich komfortabler zu händeln, als das, was du vorhast.
 
OP
Christina

Christina

Moderator
Teammitglied
Ich möchte keine Playlist.
(Eher lege ich vielleicht ein tar mit symbolischen Links an.)
Kennst du dich mit der Kommandozeile aus?
 

abgdf

Guru
Ich finde seltsam, daß Du Leerzeichen, usw. in Datei- und Verzeichnisnamen hast (das erschwert Vieles in der Shell).
Ich finde seltsam, daß Du da echte wav-Dateien liegen hast (und keine mp3s).
Ich finde seltsam, was Du da machen willst.
Ich finde seltsam, daß Du (oder jemand anders) Dolly Parton hört. :)

Meinst Du das so?
Code:
#!/bin/bash

hardlinkdir="/home/user/Dolly Parton-The Very Best Of"
suffix="wav"

if test ! -e "$hardlinkdir"
then
    mkdir -p "$hardlinkdir"
fi

nr=1
ls -1 *wav | while read i
do
    ln -T "$i" "$hardlinkdir/$nr.$suffix"
    echo "$i -> $hardlinkdir/$nr.$suffix"
    let "nr += 1"
done
 
OP
Christina

Christina

Moderator
Teammitglied
Leerzeichen gibt es doch überall und in allen Dateisystemen (vfat,ntfs,ext4,xfs,btrfs).
flac-Dateien habe ich. mp3 ist ein Lossy Codec. Ich höre hauptsächlich von CD oder SD-Card.
abgdf schrieb:
Meinst Du das so?
Ja, super! Ich habe aber hardlinkdir herausgenommen. Das brauche ich nicht.
Code:
#!/bin/bash

linkbasename="Dolly Parton-The Very Best Of"
suffix="flac"

nr=1
ls -1 *flac | while read i
do
    ln -T "$i" "$linkbasename-$nr.$suffix"
    echo "$i -> $linkbasename-$nr.$suffix"
    let "nr += 1"
done
Jetzt sollte nur noch die laufende Nummer von 01 bis 99 hochzählen und so ausgeben. Mehr Tracks hat eine CD nicht.
Ist das in dem bash-Script auch noch möglich?

P.S. Das Script könnte mich doch auch beim Starten nach linkbasename und suffix fragen, oder? Dann wäre es perfekt. :)
 

josef-wien

Ultimate Guru
Code:
ln -T "$i" "$linkbasename-$(printf "%02d" $nr).$suffix"


Variante 1: Die Werte als Parameter beim Aufruf mitgeben, im Skript heißen sie $1, $2 usw.
Variante 2:
Code:
read name_der_variablen
und danach $name_der_variablen verarbeiten.

P. S. Zum Erhöhen um 1 reicht:
Code:
let nr++
 
OP
Christina

Christina

Moderator
Teammitglied
printf und die Formatierungen kenne ich von C. Ich wusste gar nicht, dass es das in der bash auch gibt.
Vielen Dank! :)
 

abgdf

Guru
josef-wien schrieb:
P. S. Zum Erhöhen um 1 reicht:
Code:
let nr++
Ah, cool, danke! Wußte nicht, daß "let" das macht. In C/C++ und Perl gibt es das ("nr++;"), in Python nicht (nur "nr += 1").
Christina schrieb:
printf und die Formatierungen kenne ich von C. Ich wusste gar nicht, dass es das in der bash auch gibt.
Wobei es in bash ein Befehl ist ("man 1 printf"), in C eine Funktion ("man 3 printf").

Ansonsten: Freut mich, daß es so geht, wie Du es wolltest.
 
OP
Christina

Christina

Moderator
Teammitglied
Ja, wenn man weiß wie es geht, ist es eigentlich ganz einfach.
Es läuft super und spart mir viel Tipp-Arbeit.
Vielen Dank euch beiden!
Code:
#!/bin/bash

echo Link-Basisname:
read linkbasename
suffix="flac"

nr=1
ls -1 *.$suffix | while read i
do
    ln -T "$i" "$linkbasename-$(printf "%02d" $nr).$suffix"
    echo "$linkbasename-$(printf "%02d" $nr).$suffix -> $i"
    let nr++
done
 
abgdf schrieb:
Ah, cool, danke! Wußte nicht, daß "let" das macht. In C/C++ und Perl gibt es das ("nr++;"), in Python nicht (nur "nr += 1").
Bash increment performance (nur für Freaks):
Code:
((nr+=1))         # der dafür verwendete C code: nr++;    // beste performance
((nr++))          # C code: nr=nr+1;    // etwas langsamer
let nr++          # startet ext.process let, ca. 3x die Zeit von ((nr+=1))
Gruß
Gräfin Klara
 
OP
Christina

Christina

Moderator
Teammitglied
Das habe ich dazu gefunden.
Advanced Bash-Scripting Guide: The Double-Parentheses Construct
http://tldp.org/LDP/abs/html/dblparens.html
Aber, ist das „über Kreuz“ ein Tippfehler von dir? ((nr+=1)) der dafür verwendete C code: nr++;
---
Ich habe noch eine andere Frage zur bash:
Wie kann ich in einem String ein Zeichen suchen und ersetzen?
Wenn zum Beispiel das verbotene ASCII-Zeichen / im Dateinamen steht, soll das durch das Unicode-Zeichen <FF0F> ersetzt werden. Bei vfat (SD-Card) sind auch : und ? (etc.) verboten und daher durch<FF1A> und <FF1F> zu ersetzen.
---
Also, ich brauche das nicht unbedingt in dem Link-Script. Es soll eher der Lerneffekt im Vordergrund stehen.
Dann kann ich mir selber ein bash-Script schreiben, dass alle meine Musikdateien checkt und anpasst.
Mein neuer (gebrauchter) Tascam SS-R100 zeigt alle diese Zeichen an (Unicode 1.1 Juni 1993). Sieht gut aus!
https://www.compart.com/de/unicode/block/U+FF00

P.S. Mit dem Tascam kann ich endlich auch alle DAT-Bänder von meinem Papa gescheit per S/PDIF auf den PC übertragen. Die DAT-Titelmarker und die Samplingrate werden übernommen und der Tascam erstellt dann immer eine neue Datei.
https://linux-club.de/forum/viewtopic.php?f=87&t=122800&p=788449#p788504
 

josef-wien

Ultimate Guru
Die Verwendung solcher "Zeichen" ist eine unheimlich schlechte Idee. Du wirst kaum Zeichensätze finden, die sie enthalten. Du wirst noch weniger Fonts finden, die sie darstellen können. Aber Du wirst mehr als genug Programme finden, die eine solche Datei weder finden noch öffnen können.

Zum Ersetzen solltest Du Dich vor allem mit sed (und vielleicht auch noch mit awk) beschäftigen, Details müssen andere beisteuern.
 
OP
Christina

Christina

Moderator
Teammitglied
Du meinst, Unicode 1.1 vom Juni 1993 wird „heute“ immer noch gar nicht generell unterstützt?

︖ <FE16> 'Presentation Form For Vertical Question Mark' (Unicode-Version 4.1 März 2005) zeigt der Tascam z.B. nicht an.
Da ist dann nur eine Lücke zu sehen.
 
Christina schrieb:
Das habe ich dazu gefunden.
Advanced Bash-Scripting Guide: The Double-Parentheses Construct
http://tldp.org/LDP/abs/html/dblparens.html
Aber, ist das „über Kreuz“ ein Tippfehler von dir? ((nr+=1)) der dafür verwendete C code: nr++;
Kein Tippfehler.
((nr+=1)) ist eine Addition, ((nr++)) ein Increment
Bei ((nr+=1)) wird die Konstante 1 einmal nach rechts verschoben. Wenn 0 dann Increment ansonst Addition (die wir hier nicht benötigen)
Bei ((nr++)) ist das nicht so einfach wegen Endianness und 32/64 bits Systeme. ((nr++)) fordert das Erkennen von overflow.
Das geht nur über eine zusätzliche Variable. nr=nr+1 steht eigentlich für: x=nr; x+=1; overflow? nein: nr=x; Ja overflow: Fehler und nr bleibt erhalten.


Christina schrieb:
Ich habe noch eine andere Frage zur bash:
Wie kann ich in einem String ein Zeichen suchen und ersetzen?
Wenn zum Beispiel das verbotene ASCII-Zeichen / im Dateinamen steht, soll das durch das Unicode-Zeichen <FF0F> ersetzt werden. Bei vfat (SD-Card) sind auch : und ? (etc.) verboten und daher durch<FF1A> und <FF1F> zu ersetzen.
Alle diese von dir erwähnten Sonderzeichen liegen IMMER im UTF-8 EIN Byte Bereich.
Beispiel '?' = Unicode 0x3F entspricht UTF-8 0x3F.
Unicode 0xFF1F (meines Wissens für UTF-8 wäre das 0x00.ef.bc.9f) sind abseitige Sonderzeichen, die in jedem Fall falsch interpretiert werden würden.
Da die von dir gesuchten Zeichen im EIN Byte UTF-8 liegen, kannst du immer:
Code:
# VAR=${VAR//[\/\?:]/}      # entnimmt alle diese Sonderzeichen aus VAR
# VAR=${VAR//[\/\?:]/x}     # ersetzt alle diese Sonderzeichen mit einem 'x'
# VAR=${VAR//\?/}           # entnimmt nur '?'
usw.
Ein Problem gibt es bei Dateinamen mit Umlauten, weil Windows UTF-16 anwendet. Aber das ist nicht Thema

Gruß
Gräfin Klara
 
OP
Christina

Christina

Moderator
Teammitglied
# VAR=${VAR//[\/\?:]/x} # ersetzt alle diese Sonderzeichen mit einem 'x'
Welche Sonderzeichen jetzt? Alle, die im Hex-Code bei Unicode und UTF-8 nicht gleich sind?

Diese Tabelle habe ich dazu gefunden:
https://www.utf8-chartable.de/unicode-utf8-table.pl?start=65280&number=128
Aber der Unterschied Unicode oder UTF-8 im Dateinamen und die mögliche falsche Interpretation ist mir noch nicht klar.
Tut mir leid. Das ist für mich #Neuland.
 
Christina schrieb:
# VAR=${VAR//[\/\?:]/x} # ersetzt alle diese Sonderzeichen mit einem 'x'
Welche Sonderzeichen jetzt? Alle, die im Hex-Code bei Unicode und UTF-8 nicht gleich sind?
Alle Sonderzeichen, die in der Anweisung in eckiger Klammer stehen /?:
Probiere es aus
 

abgdf

Guru
Christina schrieb:
P.S. Mit dem Tascam kann ich endlich auch alle DAT-Bänder von meinem Papa gescheit per S/PDIF auf den PC übertragen. Die DAT-Titelmarker und die Samplingrate werden übernommen und der Tascam erstellt dann immer eine neue Datei.https://linux-club.de/forum/viewtopic.php?f=87&t=122800&p=788449#p788504
Ah, Du bist das; ich erinnere mich an das Thema. Netter Recorder!
Offenbar muß es bei Dir immer kompliziert und an der Grenze des Machbaren sein. Dafür sind reguläre Ausdrücke und Unicode ja mal wieder genau die richtigen Themen. :p

1. Thema "Suchen und Ersetzen". Dafür nimmt man auf der Shell meist "sed". Das verwendet so eine spezielle Konstruktion, die so aussieht:
Code:
s/dies/das/
Bei "dies" kann man auch spezielle Symbole verwenden, um bestimmte Zeichengruppen zu suchen. Das nennt man dann "regulärer Ausdruck" (Regular Expression, RegEx). Du kennst sicher den "*" von der Shell. So ähnlich (aber nicht genau so).
sed wird dann z.B. so verwendet:
Code:
echo "Kuchen" | sed "s/K/S/g"
Ergebnis: "Suchen". Das "g" am Ende in dem Ausdruck bewirkt, daß jedes Vorkommen von "K" durch "S" ersetzt wird, ohne das "g" wird nur das erste Vorkommen ersetzt.
Will man in dem RegEx-Ausdruck selbst den Slash verwenden (der ja für das Abgrenzen verwendet wird), muß man das mit einem Backslash deutlich machen, also z.B.
Code:
s/my\/directory/result/
Da dann sehr viele "/\/a\/b/\//" vorkommen können, sind reguläre Ausdrücke nicht selten schwer zu lesen, und speziell in dem Fall mit den viele "/ \/ \/ / /" bekommt man von deren Anblick die "Zahnstocherkrankheit".

2. Unicode
Argh! Das ist eines der unangenehmsten Themen. Ich würde sagen, es kommt dabei immer darauf an, wo die Unicode-Zeichen verwendet werden: In einer Datei? Auf der Konsole? In einem Programm? In der Eingabemaske einer grafischen Oberfläche? Beim Schreiben in eine Datei? Gar in einem Dateinamen?
Und dann kommt es auf die Schnittstelle an. Also, wenn man eine Datei mit Unicode von einem Programm aus liest, sollte das Programm wissen, daß die Datei in Unicode ist und welche Art von Zeichen es da also erwarten kann. Ebenso wenn ein Programm Zeichen von der Konsole liest, und die Konsole Unicode verwendet.
Meistens scheitert es gerade an dieser Schnittstelle: Die Konsole verwendet Latin-1, das Programm erwartet Unicode - schon ist das Malheur passiert.
Daraus folgt im Prinzip: Wenn man Unicode-Zeichen in Dateinamen verwendet, müßte jedes Programm, das irgendwann versucht, die Datei zu lesen, auf Unicode in Dateinamen eingestellt sein. Da wird es Programme geben, die das nicht sind. Also, ich kann davon nur abraten und will eigentlich auch keine Tipps geben, wie man es trotzdem machen würde.
 
OP
Christina

Christina

Moderator
Teammitglied
Gräfin Klara schrieb:
Alle Sonderzeichen, die in der Anweisung in eckiger Klammer stehen /?:
Danke, jetzt verstehe ich es. Und beim Doppelpunkt braucht es keinen vorangestellten Backslash.
---
abgdf schrieb:
Christina schrieb:
P.S. Mit dem Tascam kann ich endlich auch alle DAT-Bänder von meinem Papa gescheit per S/PDIF auf den PC übertragen. Die DAT-Titelmarker und die Samplingrate werden übernommen und der Tascam erstellt dann immer eine neue Datei.https://linux-club.de/forum/viewtopic.php?f=87&t=122800&p=788449#p788504
Ah, Du bist das; ich erinnere mich an das Thema. Netter Recorder!
Offenbar muß es bei Dir immer kompliziert und an der Grenze des Machbaren sein. Dafür sind reguläre Ausdrücke und Unicode ja mal wieder genau die richtigen Themen. :p
Mit etwas Geduld und Glück bekommst du so einen Tascam ohne Schramme gebraucht für unter 200€. Neu wäre mir das zu teuer gewesen.
Aber warum an der Grenze des Machbaren? ;)
Naja. So gesehen ist Linux auch an der Grenze des Machbaren. Und einige meiner Freundinnen rollen da mit den Augen. Also mir macht Linux Spaß.
Den Tipp mit dem Unicode-Schrägstrich im Dateinamen habe ich im www gelesen. Dann kam mir die Idee mit:und ?, weil die als ASCII im vfat-Dateisystem (auf der SD-Card) auch nicht erlaubt sind. Und der Tascam zeigt es an (Unicode 1.1).
Daraus folgt im Prinzip: Wenn man Unicode-Zeichen in Dateinamen verwendet, müßte jedes Programm, das irgendwann versucht, die Datei zu lesen, auf Unicode in Dateinamen eingestellt sein.
Gut. Dann weiß ich jetzt, dass Unicode im Dateinamen Probleme bereiten kann und das ganz vorsichtig einsetzen muss!
Danke!

P.S. Das xfce-Terminal steht bei mir auf: Kodierung: Vorgabe (UTF-8)
 
Oben