Gå til innhold

Linux bash - sliter med å sette sammen stringvariabel med linjeskift


Anbefalte innlegg

Skrevet

Har satt meg ned der målsetningen er å lage et script for enkel sammenføyning av videofiler. Dette lar seg forøvrig enkelt gjøres vha ffmepeg. Dette har gått helt fint, men det er et delmål jeg ikke kommer meg forbi. ffmpeg krever nemlig en liste i klartekst over videofilene som skal settes sammen, og har relativ strenge krav til formattering.

Delmål 1 - workaround for å sette inn enkel apostroff. Dette målet er nådd via prøving og feiling. Jeg lykkes med å lage et bash script som kan lage én enkelt linje.

Delmål 2 - Kjøre en for-loopover alle videofilene og skrive dette inn i en stringvariabel. Kravet er linjeskift mellom hver iterasjon. Dette er problemet mitt - jeg har testet mange (og overskrevet pga så ikke for meg at jeg ble stående helt fast på dette) måter dette skulle/burde fungere ihht divese kilder på nett.

Jeg får altså ikke bash scriptet til å sette inn dette forbaskede linjeskiftet. Når jeg skriver til skjerm henger alt sammen i en eneste lang linje.

 

Den bash-fila jeg foreløpig har sydd sammen

#!/bin/bash

listeTextformat=''

for eachLoopFile in *.MOV
do
    #echo 'file '"'"''$(pwd)'/'$eachLoopFile"'"
    listeTextformat+='file '"'"''$(pwd)'/'$eachLoopFile"'"
    listeTextformat+=$(echo -e '\n')
done

#echo "$listeTextformat"
printf '%s\n' "$listeTextformat"

At jeg benytter en separat linje i for-loopen for å (prøve) sette inn linjeskift er bare for at det er enklere å lese og når jeg gjør endringer for å prøve meg frem.

Benytter forøvrig Linux Mint 22.3 - Xfce, Engelsk menyoppsett

Videoannonse
Annonse
Skrevet (endret)
16 minutes ago, barfoo said:

Kvifor vil du det? Kva er det du vil oppnå?

vel takk for svaret, akkurat det jeg trenger og veldig hjelpsomt for andre som kommer og søker hjelp for samme problemstillingen senere :shrug:

beklager denne - trekker det tilbake, frustrasjonen tok overhånden her 🫢

 

Jeg skal starte med et større videoprosjekt - privat selvsagt så det er null budsjett å snakke om. I den anledning vil jeg etterhvert motta flere lass med separate videofiler som skal slås sammen til en stor fil.

Når dette skal gjøres en eller to ganger gjør jeg gjerne dette ved å bruke ffmpeg (kommando) og en tekstliste som er formattert ihht hva ffmpeg krever. Det er ikke veldig store arbeidet å manuelt gjøre litt søk/erstatt med en teksteditor for å få tekstfila til å tilfredstille krav til formattering.

Men nå etterhvert som jeg får inn flere grupper med videofiler fremover, så er det et ønske om automatisering av denne prosessen.

Siden prosessen videre er rett frem så ønsker jeg heller ikke bruke tid på å prøve ut diverse programmer som kanskje kan eller ikke kan gjøre det samme. Det er liksom kun dette ene lille "hullet i veien" som jeg føler jeg står fast på - resten har jeg koll på.

 

Endret av geir__hk
dum kommentar - nå skal jeg svare ordentlig
  • Liker 1
Skrevet
15 minutes ago, geir__hk said:

vel takk for svaret, akkurat det jeg trenger og veldig hjelpsomt for andre som kommer og søker hjelp for samme problemstillingen senere :shrug:

Tingen er at quotinga di er så sær at det er vanskeleg å lese, og det du spør etter gir ikkje veldig mykje meining, ergo er det god sjans for at du har xy-problem. 

  • Liker 1
Skrevet

vel, jeg gikk akkurat i den fella hvor jeg hev meg over tastaturet mens humøret kanskje ikke var på sitt beste. Dette var idiotisk av meg og jeg beklager. Jeg har nok definitivt et xy problem 😶‍🌫️

 

  • Liker 1
Skrevet
9 minutes ago, barfoo said:

Tingen er at quotinga di er så sær at det er vanskeleg å lese . . .

Ok, ser den - burde nok utelatt hele greia med quotes og heller laget et sample script som fokuserer på den ene problemstillinga. Men nå er vi her, så jeg kan prøve å forklare:

'file '"'"''$(pwd)'/'$eachLoopFile"'"

resulterer i en linje som typisk kan se ut noe som dette:

Quote

file '/lager/VIDEO/2026_0703_154640_472.MOV'

Pent er det ikke, det skal jeg være enig i. Det er godt mulig det finnes måter å omformulere på slik at det blir enklere å lese og forstå.

Skrevet
MailMan13 skrev (5 minutter siden):

Det enkle er av og til bra nok.
 

ls *.mov | xargs -I {} printf "file '%s'\n" "{}" > input.txt

 

Jeg sammenliignet både din og min, og den likte ikke apostrofer i filnavn. Ellers er de like med untak at jeg tok med realpath

Skrevet

Spør chatgpt. Du hadde hatt eit fullt fungerande script mykje raskere enn ved å forklare deg her. 

AI er rasende god på kode 😊 

Skrevet

Har du spurt Claude?

Dette er en artig og lærerik felle — du har faktisk gjort nesten alt riktig, men du blir bitt av én bestemt egenskap ved $(...).

Hvorfor linjeskiftet forsvinner

Problemet er denne linja:

bash
listeTextformat+=$(echo -e '\n')

Kommando-substitusjon — altså $(...)fjerner alltid alle linjeskift på slutten av utdataet. Det er en fast regel i bash. Så echo -e '\n' lager riktignok et linjeskift, men i det øyeblikket det pakkes inn i $(...), blir nøyaktig det linjeskiftet strippet bort igjen. Resultatet er at du legger til en tom streng, og alt havner på én lang linje. Du har med andre ord ikke gjort noe «feil» i logikken — du har bare truffet på en snublestein som er nesten umulig å se.

Enkleste fiks

Bruk bash sin egen syntaks for spesialtegn, $'...' (kalt ANSI-C quoting). Den tolker \n som et ekte linjeskift, og siden det ikke er noen kommando-substitusjon involvert, blir det stående:

 
bash
listeTextformat+=$'\n'

Bytt ut echo-linja med denne, så virker scriptet ditt.

Enda ryddigere

Du kan la printf sette linjeskiftet rett inn i selve linja, så slipper du en egen setning for det:

 
bash
#!/bin/bash

listeTextformat=''

for eachLoopFile in *.MOV
do
    listeTextformat+=$(printf "file '%s/%s'\n" "$(pwd)" "$eachLoopFile")$'\n'
done

printf '%s' "$listeTextformat"

Legg merke til at jeg måtte legge `′\n′‘∗utenfor∗‘'\n'` *utenfor* ` \nutenfor(printf ...)` her også — for printf-linjeskiftet inni ville blitt strippet av $(...) på akkurat samme måte.

Det jeg egentlig ville gjort

Hvis hele poenget er å lage lista til ffmpeg, trenger du strengt tatt ikke samle alt i en variabel i det hele tatt. La løkka skrive rett til fil:

 
bash
#!/bin/bash

for f in *.MOV
do
    printf "file '%s/%s'\n" "$(pwd)" "$f"
done > liste.txt

ffmpeg -f concat -safe 0 -i liste.txt -c copy output.MOV

Her får hver iterasjon sin egen printf med \n på slutten, og siden det aldri pakkes inn i $(...) blir linjeskiftene bevart helt uanstrengt. > liste.txt samler opp alt.

To småting verdt å nevne: enkle apostrofer rundt filnavnet (som du allerede løser fint) beskytter mot mellomrom og spesialtegn, og -safe 0 trengs fordi du bruker absolutte stier. Bruker du -safe 0 slipper du forresten $(pwd)/ helt — da holder det med printf "file '%s'\n" "$f" så lenge du kjører ffmpeg fra samme mappe.

Kjernelærdommen å ta med seg: $(...) spiser alltid avsluttende linjeskift. Når du trenger et linjeskift i en variabel, bruk $'\n' direkte, ikke via echo eller printf inni en substitusjon.

 

  • Innsiktsfullt 1
Skrevet
18 minutes ago, DukeRichelieu said:

Problemet er denne linja:

bash
listeTextformat+=$(echo -e '\n')

Vel, jøss - Hjertelig takk for mange gode råd. Dette løste jo hele problemstillinga på 1-2-3.

Ja jeg hadde tenkt på muligheta for å bare bruke >> for å skrive hver enkel linje til fil, men jeg ville ha muligheten til å gjenbruke variabelen til senere bruk også.

Det var også i tanken om jeg skulle bruke array som nødløsning om jeg ikke kom i mål med stringproblemet. Da får det bli til en annen gang.

  • Liker 1
Skrevet
geir__hk skrev (4 minutter siden):

Vel, jøss - Hjertelig takk for mange gode råd. Dette løste jo hele problemstillinga på 1-2-3.

Ja jeg hadde tenkt på muligheta for å bare bruke >> for å skrive hver enkel linje til fil, men jeg ville ha muligheten til å gjenbruke variabelen til senere bruk også.

Det var også i tanken om jeg skulle bruke array som nødløsning om jeg ikke kom i mål med stringproblemet. Da får det bli til en annen gang.

Ikke takk meg - takk Claude! 😆

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...