Bash: xargs, variabili e spazi

Forum dedicato alla programmazione.

Moderatore: Staff

Regole del forum
1) Citare in modo preciso il linguaggio di programmazione usato.
2) Se possibile portare un esempio del risultato atteso.
3) Leggere attentamente le risposte ricevute.
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.

La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.
Avatar utente
anycolouryoulike
Packager
Packager
Messaggi: 1158
Iscritto il: ven ago 10, 2007 0:00
Slackware: 12.2
Kernel: 2.6.34.8
Desktop: KDE 3.5.10

Bash: xargs, variabili e spazi

Messaggioda anycolouryoulike » lun giu 09, 2008 21:29

Sto provando a fare uno script per convertire un file audio in wav.

Codice: Seleziona tutto

#!/bin/sh
for i in $(ls *.$1)
do
    mplayer -ao pcm:fast "$i"
    rm $i
    mv audiodump.wav $(sed "s/\.$1$/.wav/")
done
Il problema è che, siccome i nomi dei file contengono anche degli spazi, mplayer prende solo la prima parola del nome.
Come si può risolvere?
E poi, si può sintetizzare l'intero script in un solo comando con una serie di xargs?

Avatar utente
umaga
Packager
Packager
Messaggi: 180
Iscritto il: lun gen 30, 2006 10:19
Slackware: 13.37
Kernel: 2.6.38.4-smp
Desktop: KDE 4.7
Località: Cagliari
Contatta:

Re: Bash: xargs, variabili e spazi

Messaggioda umaga » lun giu 09, 2008 23:07

io proverei "'$i'", cioe aggiungi le virgolette....

Avatar utente
targzeta
Iper Master
Iper Master
Messaggi: 6369
Iscritto il: gio nov 03, 2005 14:05
Nome Cognome: Emanuele Tomasi
Slackware: current
Kernel: latest stable
Desktop: IceWM
Località: Carpignano Sal. (LE) <-> Pisa

Re: Bash: xargs, variabili e spazi

Messaggioda targzeta » lun giu 09, 2008 23:11

Se ne è parlato qualche volta sul forum. Dal man di bash:
IFS The Internal Field Separator that is used for word splitting after expansion and to split lines into words with the read builtin command. The default value is "<space><tab><newline>''.

Quindi se alla variabile IFS assegni quello che ti pare a te, non hai problemi. Ecco come si potrebbe sintetizzare il tuo script:

Codice: Seleziona tutto

IFS=$(echo -e '\n\t');   # Ora il separatore di campo è <newline> e <tab>.
for file in *.$1
  do
    mplayer -ao pcm:fast:file=${file%.$1}.wav $file
done
rm -f *.$1 # Ma io non lo farei


Spina
Linux Registered User #454438
Se pensi di essere troppo piccolo per fare la differenza, prova a dormire con una zanzara -- Dalai Lama
20/04/2013 - Io volevo Rodotà 

Avatar utente
anycolouryoulike
Packager
Packager
Messaggi: 1158
Iscritto il: ven ago 10, 2007 0:00
Slackware: 12.2
Kernel: 2.6.34.8
Desktop: KDE 3.5.10

Re: Bash: xargs, variabili e spazi

Messaggioda anycolouryoulike » mar giu 10, 2008 13:32

Grazie a tutti! Ho risolto modificando la variabile IFS.

Ho letto anche le altre discussioni e il man di bash, ma non riesco a capire delle cose...
Perché questi separatori hanno un ordine?
Perché non mettere ad esempio \t\n invece di \n\t?
Ma sopratutto, se lo spazio non separa più i comandi ad esempio rm -f *.$1 non dovrebbe restituire bash: rm -f *.$1: command not found?

Mario Vanoni
Iper Master
Iper Master
Messaggi: 3174
Iscritto il: lun set 03, 2007 21:20
Nome Cognome: Mario Vanoni
Slackware: 12.2
Kernel: 3.0.4 statico
Desktop: fluxbox/seamonkey
Località: Cuasso al Monte (VA)

Re: Bash: xargs, variabili e spazi

Messaggioda Mario Vanoni » mar giu 10, 2008 14:51

anycolouryoulike ha scritto:Ma sopratutto, se lo spazio non separa più i comandi ad esempio rm -f *.$1 non dovrebbe restituire bash: rm -f *.$1: command not found?


rm(1) e` un commando, la bash(1) lo trova, anche senza argomenti,
rm -f == ignore nonexistent files, never prompt
rrmm -f *
bash: rrmm: command not found

Avatar utente
targzeta
Iper Master
Iper Master
Messaggi: 6369
Iscritto il: gio nov 03, 2005 14:05
Nome Cognome: Emanuele Tomasi
Slackware: current
Kernel: latest stable
Desktop: IceWM
Località: Carpignano Sal. (LE) <-> Pisa

Re: Bash: xargs, variabili e spazi

Messaggioda targzeta » mar giu 10, 2008 15:39

anycolouryoulike ha scritto:....
Perché non mettere ad esempio \t\n invece di \n\t?
....

Questa domanda è carina, me la pose come domanda a trabocchetto il mio sistemista di laboratorio all'università (ed io ci cascai). In realtà, ora sono al lavoro e non ho linux, ma ci dovrebbe essere scritto nel man della bash che elimina l'ultimo \n, l'ordine non conta, se non fosse per questo. Infatti
"\ns\t" è uguale a "\n\ts". Il problema si pone solo se alla fine c'è un '\n', come descritto nel man della bash.

Spina
Linux Registered User #454438
Se pensi di essere troppo piccolo per fare la differenza, prova a dormire con una zanzara -- Dalai Lama
20/04/2013 - Io volevo Rodotà 

Avatar utente
anycolouryoulike
Packager
Packager
Messaggi: 1158
Iscritto il: ven ago 10, 2007 0:00
Slackware: 12.2
Kernel: 2.6.34.8
Desktop: KDE 3.5.10

Re: Bash: xargs, variabili e spazi

Messaggioda anycolouryoulike » mar giu 10, 2008 15:44

Continuo a non capire...
In questa situazione ad esempio:

Codice: Seleziona tutto

root@darkstar:~# IFS=$(echo -e '\n\t')
root@darkstar:~# ls
loadlin16c.txt  loadlin16c.zip
Se faccio ls loadlin16c.txt loadlin16c.zip me li lista tutti e due. Non dovrebbe considerarli come un file unico e darmi ls: cannot access loadlin16c.txt loadlin16c.zip: No such file or directory?
Lo spazio non separa più i campi, no?

Avatar utente
anycolouryoulike
Packager
Packager
Messaggi: 1158
Iscritto il: ven ago 10, 2007 0:00
Slackware: 12.2
Kernel: 2.6.34.8
Desktop: KDE 3.5.10

Re: Bash: xargs, variabili e spazi

Messaggioda anycolouryoulike » mar giu 10, 2008 15:47

spina ha scritto:
anycolouryoulike ha scritto:....
Perché non mettere ad esempio \t\n invece di \n\t?
....

Questa domanda è carina, me la pose come domanda a trabocchetto il mio sistemista di laboratorio all'università (ed io ci cascai). In realtà, ora sono al lavoro e non ho linux, ma ci dovrebbe essere scritto nel man della bash che elimina l'ultimo \n, l'ordine non conta, se non fosse per questo. Infatti
"\ns\t" è uguale a "\n\ts". Il problema si pone solo se alla fine c'è un '\n', come descritto nel man della bash.

Spina
Non ho capito una parola...
Prima meglio che mi legga il man.

Avatar utente
Paoletta
Staff
Staff
Messaggi: 3955
Iscritto il: lun apr 25, 2005 0:00
Slackware: 14.2 - 64 bit
Desktop: fluxbox
Località: Varese

Re: Bash: xargs, variabili e spazi

Messaggioda Paoletta » mar giu 10, 2008 16:37

la cosa poteva anche essere risolta in questo modo:

Codice: Seleziona tutto

#!/bin/sh                                                                       
tmp=$(ls -1 *.$1)
for i in "$tmp"
do
    ...codice...
done

Avatar utente
anycolouryoulike
Packager
Packager
Messaggi: 1158
Iscritto il: ven ago 10, 2007 0:00
Slackware: 12.2
Kernel: 2.6.34.8
Desktop: KDE 3.5.10

Re: Bash: xargs, variabili e spazi

Messaggioda anycolouryoulike » mer giu 11, 2008 13:11

Leggendo man bash ho scoperto diverse cose.
man bash ha scritto:Words of the form $'string' are treated specially. The word expands to string, with backslash-escaped characters replaced as specified by the ANSI C standard.
Quindi invece di usare un echo basta IFS=$'\t\n' e credo non ci sia nemmeno bisogno di mettere prima il \t perché non è una sostituzione di comando. Infatti nella sotituzione di comando http://www.slacky.eu/forum/viewtopic.php?p=66510#p66510...

La questione dell'ls loadlin16c.txt loadlin16c.zip ancora non l'ho capita però...
Qualcuno mi potrebbe chiarire le idee?

@Paoletta: questo mi dà lo stesso errore:

Codice: Seleziona tutto

#!/bin/sh
tmp=$(ls -1 *.wma)
for i in "$tmp"
do
    mplayer -ao pcm:fast:name=${i%.wma}.wav $i
done

Avatar utente
anycolouryoulike
Packager
Packager
Messaggi: 1158
Iscritto il: ven ago 10, 2007 0:00
Slackware: 12.2
Kernel: 2.6.34.8
Desktop: KDE 3.5.10

Re: Bash: xargs, variabili e spazi

Messaggioda anycolouryoulike » ven giu 13, 2008 13:47

Ma questa cosa funziona solo quando gli pare?

Codice: Seleziona tutto

root@darkstar:~# ls -1
loadlin16c.txt
loadlin16c.zip
prova.sh
root@darkstar:~# cat prova.sh
#!/bin/sh
IFS=$(echo -e '\n\t');
ls loadlin16c.txt loadlin16c.zip > log
root@darkstar:~# ./prova.sh
root@darkstar:~# cat log
loadlin16c.txt
loadlin16c.zip
root@darkstar:~# mkdir prova
root@darkstar:~# cd prova/
root@darkstar:~/prova# touch "loadlin16c.txt loadlin16c.zip"
root@darkstar:~/prova# ../prova.sh
ls: cannot access loadlin16c.txt: No such file or directory
ls: cannot access loadlin16c.zip: No such file or directory
root@darkstar:~/prova# ls -1
loadlin16c.txt loadlin16c.zip
log
root@darkstar:~/prova# cat log
root@darkstar:~/prova#

Avatar utente
Paoletta
Staff
Staff
Messaggi: 3955
Iscritto il: lun apr 25, 2005 0:00
Slackware: 14.2 - 64 bit
Desktop: fluxbox
Località: Varese

Re: Bash: xargs, variabili e spazi

Messaggioda Paoletta » ven giu 13, 2008 14:10

dove mi trovo non ho nè mplayer nè il tempo per verificare; il mio esempio era solo per mostrare il fatto che con ls -1 si ha la possibilità di evirare il riassegnamento di IFS (cosa secondo me sensata, infatti se poi eseguo un altro script che fa conto sul valore "giusto" di IFS potrei avere dei malfunzionamenti); infatti:

Codice: Seleziona tutto

#!/bin/sh                                                                       
tmp=$(ls -1 *.wma)
for i in "$tmp"
do
    mplayer -ao pcm:fast "$i"
    rm "$i"
    mv audiodump.wav $(sed "s/\.$1$/.wav/")
done


dovrebbe funzionare; credo che in

Codice: Seleziona tutto

 mplayer -ao pcm:fast:file=${file%.$1}.wav $file
manchi qualche ""

Avatar utente
anycolouryoulike
Packager
Packager
Messaggi: 1158
Iscritto il: ven ago 10, 2007 0:00
Slackware: 12.2
Kernel: 2.6.34.8
Desktop: KDE 3.5.10

Re: Bash: xargs, variabili e spazi

Messaggioda anycolouryoulike » sab giu 14, 2008 0:26

Il problema quindi non è nella stringa di mplayer ma nel ciclo for...
Domani faccio un paio di prove, grazie.

Avatar utente
anycolouryoulike
Packager
Packager
Messaggi: 1158
Iscritto il: ven ago 10, 2007 0:00
Slackware: 12.2
Kernel: 2.6.34.8
Desktop: KDE 3.5.10

Re: Bash: xargs, variabili e spazi

Messaggioda anycolouryoulike » dom giu 15, 2008 14:28

Adesso credo di aver capito.
IFS lo usa solamente for per determinare i campi da passare in questo caso a mplayer. Anche con ls -1 conta anche gli spazi come separatori oltre ai ritorni a capo, e l'effetto quindi è lo stesso.
Non credo sia possibile senza modificare l'IFS. È l'unico modo per fare in modo che il for passi a mplayer i comandi riga per riga senza contare gli spazi.
Se ho capito male correggetemi pure.

Codice: Seleziona tutto

#!/bin/sh
IFS=$'\t\n'
for file in $(ls *.$1)
do
    mplayer -ao pcm:fast:file=${file%.$1}.wav $file
done
exit

Avatar utente
targzeta
Iper Master
Iper Master
Messaggi: 6369
Iscritto il: gio nov 03, 2005 14:05
Nome Cognome: Emanuele Tomasi
Slackware: current
Kernel: latest stable
Desktop: IceWM
Località: Carpignano Sal. (LE) <-> Pisa

Re: Bash: xargs, variabili e spazi

Messaggioda targzeta » dom giu 15, 2008 22:08

Ciao,
innanzi tutto grazie per la dritta sul $'', si vede che, o mi è sfuggita oppure che l'hanno aggiunta da poco.....e devo dire meno male, ci si risparmia di eseguire un echo ogni volta che si vuole modificare IFS.

Quello che cerchi, lo trovi come "word splitting" sotto la sezione EXPANSION del man della bash.
In pratica che succede, se ai parametri viene fatta una 'espansione di parametro', una 'sostituzione di comando' oppure una 'espansione aritmetica', allora ai parametri viene fatto anche il 'word splitting', ovvero si divide il risultato di suddetta espensione in parole, usando come separatore di parole, ogni carattere contenuto nella variabile 'IFS'.

Facciamo degli esempi, impostando:

Codice: Seleziona tutto

IFS=$'a\n'
ovvero, come separatore di parole i caratteri 'a' e '\n'.

Esempio:

Codice: Seleziona tutto

\ls casa
ls: impossibile accedere a casa: No such file or directory
In questo caso, al parametro 'casa', la shell non ha fatto nessuna delle tre espansione su dette, quindi bash invoca 'ls' passandogli 'casa' come parametro.

Nel seguente esempio invece:

Codice: Seleziona tutto

casa="mamma"
\ls $casa
ls: impossibile accedere a m: No such file or directory
ls: impossibile accedere a mm: No such file or directory
al parametro '$casa' viene fatta l'espansione di parametro, per cui bash invoca 'ls' passandogli 'm' e 'mm'.

Ora dovrebbe esserti chiaro perchè, se IFS è impostata di default, quindi a '<spazio><tab><newline>', ed in una directory hai i file:
casa
ciao mamma

Ottieni due risultati differenti se esegui:

Codice: Seleziona tutto

for file in *; do  echo $file; done
casa
ciao mamma
e se esegui

Codice: Seleziona tutto

for file in $(\ls *); do  echo ${file}; done
casa
ciao
mamma

Ed anche perchè, nel thread, http://www.slacky.eu/forum/viewtopic.php?f=2&t=25031 hai detto una sciocchezzuola (riferendoti all'ultimo script postato da aschenaz) ;).

Ringraziandoti ancora per la dritta su $'' e con la speranza di esserti stato di aiuto,
Spina
Linux Registered User #454438
Se pensi di essere troppo piccolo per fare la differenza, prova a dormire con una zanzara -- Dalai Lama
20/04/2013 - Io volevo Rodotà 


Torna a “Programmazione”

Chi c’è in linea

Visitano il forum: Nessuno e 1 ospite