while read hibás beadott sorok

Fórumok

Helo!

 

Egy olyan problémába futottam, hogy fájlból beadott sorokat csonkítja a script.

 

#!/bin/ksh

defdir=/out
defdir2=/out2

while IFS= read -r line
do

ffmpeg -i "$defdir/$line.flv" -c copy -copyts "$defdir2/$line.mp4"

done < lista.txt
 

 

A lista.txt-ben ez van:

 

0003705e-f2d9-4502-93af-fa242d8ba549
0004eb9c-d777-46ad-89fb-e8771e56d4c1
00096af6-e669-4527-9e28-e2761e38300a
000ceeb8-f7a9-4b34-a23b-b982d18f2898
00293bf0-ed13-42f0-9598-7fb81f02fa3d
002f175c-54c0-40a1-a567-2228292294bc
00315924-2cb5-4f0b-b419-2d2adb0a1755
003a613c-aa56-4a28-925a-5ba0f55ee6b1
0053a025-88bf-4a12-844e-67ff11dc53ee
0056ddca-d997-4f4d-a006-77ba117fdf04
005f8681-cfe4-48f0-ab41-90f06fcad3f5
0064c899-e507-401e-9175-e646ae4f3b39
006c9351-fe33-415d-82f3-b5970aad0a78
007d6273-5afc-4777-b35e-fe47cd0dd90a
008269db-3a7d-4848-8f45-5aafe8622c5a
0082cfb2-6b7f-4782-a072-e2f643cfe286
 

Az elsőt rendesen kiírja, a másodikról már az első 0 hiányzik. Ahol három 1-es van az elején, azt leszedi, de van amikor üres sor megy be. Ezt miért csinálja?

Hozzászólások

Nekem megy, probléma nélkül: ksh, Version: 93u+20120801-3.4

Annyi, hogy tettem egy echo-t a ffmpeg elé.

Ez de gaz... Amikor rejtett side effect van benne. Shellt bottal sem szabad piszkalni, csak trivialis dolgokra, amikre Pythont vagy mas ertelmes nyelvet meg nem eri meg hasznalni.

Raadasul az egy valid bash kod volt, eszre sem vettem ezert a ksh-t. Mindket shell ilyen. Nem a while kapja meg, hanem aki marja.

Ebben semmi side effect nincs, itt a kód jól leírja, hogy egyszer a while feltétele, egyszer meg a ciklusmagja olvassa a bemenetet. Mint amikor while(i++) van egy programozási nyelvben, és a ciklusmagban is i++-olsz.

Pontosan ugyanaz.

Itt az elbaszás az, hogy az ffmpeg olvas a standard inputról akkor is, ha megmondod neki expliciten, hogy mi az input állomány. Mit akarna ilyenkor olvasni az stdinról?

Ha jól tudom, van interaktív módja, s talán yes/no, de ebben nem vagyok azért ennyire biztos. Vagy csak mindenképpen benyeli az inputot, aztán később jön rá, hogy explicit meg van adva neki a file, s akkor nem kezd vele semmit.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Nagyon bután van ez leírva a dokumentációban.

-stdin Enable interaction on standard input. On by default unless standard input is used as an input. To explicitly disable interaction you need to specify -nostdin.

Egy default bekapcsolhatóságát dokumentálják, miközben leírják, hogy ezt expliciten kikapcsolni kell.

Erősen javallom, hogy az ffmpeg-nek adj egy

-nostdin

kapcsolót, mert a kis mocsok képes néha elszedni a standard inputot a read elől. Már szívtam ezzel korábban. De lehet így is:

ffmpeg itt van sok minden </dev/null

De a -nostdin kapcsoló elegánsabb. Az ffmpeg manualja a -stdin kapcsoló taglalásakor emlékezik meg erről.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Köszi, majd kipróbálom az nostdin-t. Valószínűleg az lesz a baja.

 

Most így oldottam meg:

 

for name in $(cat lista.txt); do

ffmpeg -i "$defdir/${name}.flv" -c copy -copyts "$defdir2/${name}.mp4"
 

done

 

Így jól működött.

OK, hogy már van megoldás, de akkor már legyünk elegánsak. Rendes shellben a $(cat file) konstrukció ekvivalens a $(< file) formával, csak gyorsabb és olcsóbb. (man bash ; man ksh - és mindkét esetben /\$\( )

Az lehet, de ha a cillusból egy eredményt változóban akarsz kihozni, az nem fog sikerülni, mert a pipe miatt az egész ciklus subshellben fut. Ezzel szemben, ha a file-t a ciklusba irányítot, akkor az eredeti shellben fut, így az eredményhez is hozzáférsz. Persze pipe-olt dolgokból is lehet eredményt kihozni. Én úgy szoktam, hogy nemes egyszerűséggel stdout-ra írok a subshellben olyasmit, hogy variable=value, ebből akár többet is, majd az egész kimenetét egy v=$(itt van a program) szerkezettel átadom v-nek, végül egy eval "$v" az eredeti shellben adja a változóknak az értékeket, amelyet a subshellben mondott a programíró program. :)

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Szerkesztve: 2020. 04. 30., cs – 14:16

Nem válaszként írom, hátha javítani kell. Teve, azok a kukacok kellenek, vagy csak azzal összefüggésben kerültek oda, hogy különböző billentyű layout-on mindkettő shift-2?

Ja, és minek a cat meg a pipe?

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Az a debuggolásnál esetleg segíthet mutatni a sorokat, különösen, ha szóközt tartalmaznak (vagy a sort tartalma az, hogy -n.
Vagy lehet igy is:

while read -r name; do
  echo @"$name"@ </dev/null
done <lista.txt

Szerk: Visszaraktam a </dev/null-t, az fontos a jelen példában.