grep es sed szokozt tartalmazo filenevekben

Hali!
Adott egy konyvtar, amiben van tobb alkonyvtar, azokban tobb file. Bizonyos file-okban bizonyos szoveget le akarok cserelni ("ISO-8859-1"-et "UTF-8"-ra, de nem HTML vagy PHP fileok, config fileok. Itt az elso probaban meg nem is akarok cserelni, csak cat segitsegevel elolvasni ezeket a file-okat.)

Elso otlet:
grep -r keresem * | awk '{print $}' > tmpfile
while read ; do cat $REPLY ; done < tmpfile

Ez ugye visszadna "tmpfile"-ban azon file-ok neveit, amiben benne van a "keresem" szo, masodik sor pedig elolvasna ezeket a file-okat.(Nem az, amit en akarok, de ezen konnyebben mutatom). Es itt jon a bibi: a filenevek szokozt tartalmaznak . Tobb probam is volt:
grep -r keresem * | awk '{print $}' | sed '/\ /\\/g' > tmpfile
a tmpfileban gyonyoru:
xx/yy/file\ neve
De ha ugyanezt beolvastatom a "while read" paranccsal, valami ertelmezi a "\" jelet es eltunteti :(

Valami otlet? Persze, megcsinalhatnam, hogy mondjuka "detox" proggival eltuntetem az osszes szokozt es ugy futtatom, csak sajnos ezek a file-ok havonta frissulnek :(

Hozzászólások

Probald meg lecserelni a sed delimitereit valami masra, pl:

sed -e 's|cucc|masikcucc|g'

Korantsem biztos, hogy ez a baj, de egy probat meger.

"$REPLY" a megoldás, tehát "-ök közé kell tenni,
nekem amúgy az awk-s cucc nem megy, biztos elírtad, én cut-ot szoktam ilyen dolgokra használni, ilyesmiképp:

cut -f 1 -d ':'

Update: meg ilyen is van: grep -lr valami .

Ujabb, hasonlo problemam akadt, csak most mplayerrel. Itt egy file reszlete, ami a parameterknet megkapott kiterjesztesu filokat kigyujti egy listaba, aztan az mplayer vegigszalad rajta, hoyg kideritse az audio/video codecet es bitratat. Gondoltam, rakok bele egy szamlalot is, hogy lassam, hol tart :)
DB=$(ls *$1 | wc -l) #DB file
ls *$1 > ListAbA #filenevek
AKT=1 # aktualis
while read # ciklus
do echo $AKT'/'$DB # hanyadiknal tart
do echo $REPLY # Melyik a file
mplayer -ao null -vo null -endpos 1 $REPLY 2>/dev/null| grep 'Playing\|kbps\|kbit' >> bitrate0.log
AKT=$(expr $AKT + 1) # kovetkezo file
done < ListAbA # es ennyi.

A vicc az, hogyha az mplayer kezdetu sort kikommentezem, akkor gyonyoruen azt csinalja, amit akarok, kiirja az osszes filenevet egyesevel. Ha bent van az mplayer sor, akkor csak a legelso filet nezi meg (de tovabb szamlal, viszont az mplayer olyan, mintha nem kapna filenevet.

Ez viszont gyonyoruen mukodik, szoval a meghivott kiterjesztesu fileokat atnezi.
#mplayer -ao null -vo null -endpos 1 *$1 2>/dev/null| grep 'Playing\|kbps\|kbit' >> bitrate0.log

Mi a nyavalyatol lehet ez?

Oke, akkor ez a (nem) mukodo.

DB=$(ls *$1 | wc -l) #DB file
ls *$1 > ListAbA #filenevek
AKT=1 # aktualis
while read # ciklus
do echo $AKT'/'$DB # hanyadiknal tart
mplayer -ao null -vo null -endpos 1 $REPLY 2>/dev/null| grep 'Playing\|kbps\|kbit' >> bitrate0.log
AKT=$(expr $AKT + 1) # kovetkezo file
done < ListAbA # es ennyi.

Ha az mplyaer sor helyett a kovetkezo van, gond egy szal sem:

echo $REPLY # Melyik a file

Sot. Itt az alabbi file, ami mukodik :

#!/bin/sh
while read
do
t=`echo $REPLY | awk '{print $1}'`
v=`echo $REPLY | awk '{print $2}'`
a=`echo $REPLY | awk '{print $3}'`
nt=`echo $REPLY | awk '{print $4}'`
rm frameno.avi
rm divx2pass.log
mencoder $t -mc 0 -oac mp3lame -ovc frameno -o frameno.avi -lameopts cbr:br=$a 1> $t.0.log 2>&1
echo "$t 0 menet kesz" >> code.log
mencoder $t -oac copy -mc 0 -ovc xvid -o $nt -xvidencopts bitrate=$v:pass=1 1> $t.1.log 2>&1
echo "$t 1 menet kesz" >> code.log
mencoder $t -oac copy -mc 0 -ovc xvid -o $nt -xvidencopts bitrate=$v:pass=2 1> $t.2.log 2>&1
echo " $t .2 menet kesz" >> code.log
done < bitrate.log

bitrate.log fileban vannak felsorolva a filmek
nev TAB video_bitrata TAB audio_bitrata TAB uj_nev
nev TAB video_bitrata TAB audio_bitrata TAB uj_nev
.
.
Es gyonyoruen vegigmegy a file-on sorban atkodolva a filmeket (mpg-bol vagy wmv-bol szoktam avit csinalni). Tehat ez a code azt csinalja, amit szeretnek, mig a fenti nem.
De akar ki is probalhatjatok, 3-4 film egy konyvtarba, raengedni az elso kodot, kivancsi vagyok, csak nalam nem mukodik, vagy mashol sem...

szerintem szokd meg, hogy a file-ok sokasagan vegigmeno ciklus az mindig find -print0 | while read -r -d $'\0', es a ciklus belsejeben mindig "$REPLY"


DB=$(ls *$1 | wc -l) #DB file
AKT=1
#ls *$1 
find . -name "*$1" -print0 -maxdepth 1 |
  while read -r -d $'\0' 
    do echo $AKT'/'$DB # hanyadiknal tart
    mplayer -ao null -vo null -endpos 1 "$REPLY" 2>/dev/null | 
        grep 'Playing\|kbps\|kbit' >> bitrate0.log
        AKT=$(expr $AKT + 1) # kovetkezo file
  done  # es ennyi. 

ha nem csak az aktualis dirben, hanem rekurzivan az osszes alatta levo dirben is szeretned ezt megoldani, akkor hagyd el a "-maxdepth 1" kapcsolot a find parancsbol.

a problema komoly, a szerteagazo gyermek-problemak sok kedves hacker munkajat tettek mar lehetove a vilagban. Erre az alapproblemara a megoldas:


find | xargs
vagy find | while read

visoznt ez elesik a whitespacen, mint minden, es a file neve tartalmazhat ujsor karaktert is (igazabol csak '\0' es '/' karektereket nem tartalmazhat) Erre van egy gnu extension (linuxokon van) ez a print0 es tarsai. Ezek a find kimenetet '\0'-val szeparaljak (ami invalid file char) tehat nem lesz utkozes. A

read -d $'\0'

meg kifejezetten bash, szoval nem tul portabilis, de linuxon jok ezek.


find -print0 | xargs -0 -L1 command
find -print0 | while read -r -d $'\0' ; do command "$REPLY" ; done

Okes, itt egy cklus, ami helyesen vegig megy a fileokon, hasznaljuk ezt. Nezzuk most a feladatot: csak azon file-ok, amiben szerepel a keresett kifejezes:


find -print0 | 
    while read -r -d $'\0' ; do 
        if grep -q 'keresem' "$REPLY" ; then
            sed -i -e 's/keresem/erre/g" "$REPLY"
        fi 
    done

a megoldas lassabb, mintha a grep lenne kivul (a grep tobbszori meghivasa miatt) azonban az esetleges sorvegjeleket nem tudom mashogy hogyan megoldani.
Ja, a

sed -i

is gnu specific ha jol emlekszem.

De ha ugyanezt beolvastatom a "while read" paranccsal, valami ertelmezi a "\" jelet es eltunteti :(

man bash (tudom, hosszu) read builtin:


-r     Backslash does not act as an escape character.  The back-
       slash is considered to be part of the line.  In  particu-
       lar,  a  backslash-newline pair may not be used as a line
       continuation.