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?
- 328 megtekintés
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é.
- A hozzászóláshoz be kell jelentkezni
detto, szinten jo, ugyanaz a verzio (nagyjabol)
- A hozzászóláshoz be kell jelentkezni
És ezzel nem is a valós helyzetet debugoltad, hiszen így már az ffmpeg nem falatozik a standard inputból, hiszen nem is fut. :)
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Jaja, ezért is írtam bele.
- A hozzászóláshoz be kell jelentkezni
Egyebkent sem. A while ciklus kapja a file tartalmat standard inputon. Az ffmpeg meg semmit sem.
A set -x hasznalata sokat segit a debugolasban, mert latszik, mi mire helyettesitodik, stb.
- A hozzászóláshoz be kell jelentkezni
Szerintem meg:
seq 10 | while read; do echo "$REPLY"; read; sleep 0.1; done
1
3
5
7
9
Fel lehet szedni a ciklusmagban is a while read-je elől adatot.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
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.
- A hozzászóláshoz be kell jelentkezni
Akár tetszik, akár nem, ez ilyen. ;)
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
"Shellt bottal sem szabad piszkalni, csak trivialis dolgokra, amikre Pythont vagy mas ertelmes nyelvet meg nem eri meg hasznalni"
Azert ez eleg eros es alaptalan kijelentes.
- A hozzászóláshoz be kell jelentkezni
Szándékosan túlzó. De nem alaptalan. Egyedi logika szerint működik, eltér a hagyományos programnyelvektől.
- A hozzászóláshoz be kell jelentkezni
Kb bármelyik programozási nyelvben is ugyanígy lehet ilyet írni.
- A hozzászóláshoz be kell jelentkezni
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?
- A hozzászóláshoz be kell jelentkezni
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
- A hozzászóláshoz be kell jelentkezni
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.
- A hozzászóláshoz be kell jelentkezni
Ilyenkor van az, hogy úgy tekintem, nem tudom, mi a default, viszont tudom, mit szeretnék, s akármi is legyen az, kiírom a kívánatos paramétert.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
amikre Pythont vagy mas ertelmes nyelvet meg nem eri meg hasznalni.
Legalabb nem a szokozok szamaval kell programozni. Az is valami ;)
- A hozzászóláshoz be kell jelentkezni
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
- A hozzászóláshoz be kell jelentkezni
Hmm, miket tanul az ember...
- A hozzászóláshoz be kell jelentkezni
Ahhoz nekem is ki kellett tépni a hajam egy részét, mire rájöttem... :)
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
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.
- A hozzászóláshoz be kell jelentkezni
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 /\$\( )
- A hozzászóláshoz be kell jelentkezni
Szerintem a cat $file sokkal jobban olvasható. Ha meg performance kell akkor ne shellben álljunk neki.
- A hozzászóláshoz be kell jelentkezni
Írtad:
és mindkét esetben /\$\( )
Ezen mit értesz?
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
A záró zárójel nem a pattern része, csak a \$\( :)
- A hozzászóláshoz be kell jelentkezni
És ezen mit ért?
/\$\(
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Keressen rá a $( -re.
- A hozzászóláshoz be kell jelentkezni
Jaj, basszus, regexp a man find-jában! :) Azon gondolkodtam, hogy a shellben nem kell escape-elni, mi a fenének írja ezt Zahy. Pedig írta is, hogy man, de valahogy nem gondoltam, hogy ilyen szinten szájbarágós a javaslat. :)
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Rendes shellben a $(cat file) konstrukció ekvivalens a $(< file) formával
Na, tok jo, ma sem lettem butabb :)
- A hozzászóláshoz be kell jelentkezni
a $(cat file) konstrukció ekvivalens a $(< file) formával
Csak arra kell figyelni, nehogy véletlenül $(> file) -t írjál :-)
(nekem már sikerült, nagyon gyorsan visszaszoktam a $(cat file) -ra)
- A hozzászóláshoz be kell jelentkezni
És akkor ott van még a process substitution, amellyel szintén nem keverendő: <(list) és >(list). :)
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Off: ez a `$(cat lista.txt)` nem lesz egészen jó, ha a fájl nagyon nagy, vagy ha szóközök is vannak benne. Inkább az előző módszerrel:
cat lista.txt | while read -r name; do
echo @"$name"@ </dev/null
done
- A hozzászóláshoz be kell jelentkezni
Akartad írni:
while read -r name; do
echo @"$name"@ </dev/null
done < lista.txt
(Pardon, valahogy nem tűnt fel, hogy ez a forma már szerepel.)
- A hozzászóláshoz be kell jelentkezni
hat ez valoban szebb, de ha ciklusban nem csak egy echo van, akkor golyozik a szemem hogy ki van kivel :(
lehet csunyabb, de nekem egyertelmubb hogy "cat |while read" mi tortenik
A vegtelen ciklus is vegeter egyszer, csak kelloen eros hardver kell hozza!
- A hozzászóláshoz be kell jelentkezni
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
- A hozzászóláshoz be kell jelentkezni
Sőt,
echo "@${name}@"
Legalábbis én igyekszem a teljes paramétert bezárójelezni, nekem egyértelműbb.
- A hozzászóláshoz be kell jelentkezni
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
- A hozzászóláshoz be kell jelentkezni
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.
- A hozzászóláshoz be kell jelentkezni