Repository 32bit  Forum
Repository 64bit  Wiki

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.

Bash: xargs, variabili e spazi

Messaggioda anycolouryoulike » lun giu 09, 2008 20: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
anycolouryoulike
Packager
Packager
 
Messaggi: 1158
Iscritto il: gio ago 09, 2007 23:00
Slackware: 12.2
Kernel: 2.6.34.8
Desktop: KDE 3.5.10

Re: Bash: xargs, variabili e spazi

Messaggioda umaga » lun giu 09, 2008 22:07

io proverei "'$i'", cioe aggiungi le virgolette....
Avatar utente
umaga
Packager
Packager
 
Messaggi: 180
Iscritto il: lun gen 30, 2006 10:19
Località: Cagliari
Slackware: 13.37
Kernel: 2.6.38.4-smp
Desktop: KDE 4.7

Re: Bash: xargs, variabili e spazi

Messaggioda targzeta » lun giu 09, 2008 22: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
targzeta
Iper Master
Iper Master
 
Messaggi: 6186
Iscritto il: gio nov 03, 2005 14:05
Località: Carpignano Sal. (LE) <-> Pisa
Nome Cognome: Emanuele Tomasi
Slackware: current
Kernel: latest stable
Desktop: IceWM

Re: Bash: xargs, variabili e spazi

Messaggioda anycolouryoulike » mar giu 10, 2008 12: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?
Avatar utente
anycolouryoulike
Packager
Packager
 
Messaggi: 1158
Iscritto il: gio ago 09, 2007 23:00
Slackware: 12.2
Kernel: 2.6.34.8
Desktop: KDE 3.5.10

Re: Bash: xargs, variabili e spazi

Messaggioda Mario Vanoni » mar giu 10, 2008 13: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
Mario Vanoni
Iper Master
Iper Master
 
Messaggi: 3174
Iscritto il: lun set 03, 2007 20:20
Località: Cuasso al Monte (VA)
Nome Cognome: Mario Vanoni
Slackware: 12.2
Kernel: 3.0.4 statico
Desktop: fluxbox/seamonkey

Re: Bash: xargs, variabili e spazi

Messaggioda targzeta » mar giu 10, 2008 14: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
targzeta
Iper Master
Iper Master
 
Messaggi: 6186
Iscritto il: gio nov 03, 2005 14:05
Località: Carpignano Sal. (LE) <-> Pisa
Nome Cognome: Emanuele Tomasi
Slackware: current
Kernel: latest stable
Desktop: IceWM

Re: Bash: xargs, variabili e spazi

Messaggioda anycolouryoulike » mar giu 10, 2008 14: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: gio ago 09, 2007 23: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 14: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
anycolouryoulike
Packager
Packager
 
Messaggi: 1158
Iscritto il: gio ago 09, 2007 23:00
Slackware: 12.2
Kernel: 2.6.34.8
Desktop: KDE 3.5.10

Re: Bash: xargs, variabili e spazi

Messaggioda Paoletta » mar giu 10, 2008 15: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
Paoletta
Staff
Staff
 
Messaggi: 3903
Iscritto il: dom apr 24, 2005 23:00
Località: Varese
Slackware: 13.1
Desktop: fluxbox

Re: Bash: xargs, variabili e spazi

Messaggioda anycolouryoulike » mer giu 11, 2008 12: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: gio ago 09, 2007 23: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 12: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
anycolouryoulike
Packager
Packager
 
Messaggi: 1158
Iscritto il: gio ago 09, 2007 23:00
Slackware: 12.2
Kernel: 2.6.34.8
Desktop: KDE 3.5.10

Re: Bash: xargs, variabili e spazi

Messaggioda Paoletta » ven giu 13, 2008 13: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
Paoletta
Staff
Staff
 
Messaggi: 3903
Iscritto il: dom apr 24, 2005 23:00
Località: Varese
Slackware: 13.1
Desktop: fluxbox

Re: Bash: xargs, variabili e spazi

Messaggioda anycolouryoulike » ven giu 13, 2008 23: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: gio ago 09, 2007 23: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 13: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
anycolouryoulike
Packager
Packager
 
Messaggi: 1158
Iscritto il: gio ago 09, 2007 23:00
Slackware: 12.2
Kernel: 2.6.34.8
Desktop: KDE 3.5.10

Re: Bash: xargs, variabili e spazi

Messaggioda targzeta » dom giu 15, 2008 21: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à
Avatar utente
targzeta
Iper Master
Iper Master
 
Messaggi: 6186
Iscritto il: gio nov 03, 2005 14:05
Località: Carpignano Sal. (LE) <-> Pisa
Nome Cognome: Emanuele Tomasi
Slackware: current
Kernel: latest stable
Desktop: IceWM

Prossimo

Torna a Programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 1 ospite