Nunca, nunca lo usesfor foo in $(cat bar) . Este es un error clásico, comúnmente conocido como bash pitfall number 1 . En su lugar, debe usar:
while IFS= read -r file; do mv -- "$file" "new_place/$file"; done < file_list.txt
Cuando se ejecuta el forbucle, golpe del aplicará wordsplitting a lo que lee, lo que significa que a strange blue cloudse puede leer como a, strange, bluey cloud:
$ cat files
a strange blue cloud.txt
$ for file in $(cat files); do echo "$file"; done
a
strange
blue
cloud.txt
Comparar con:
$ while IFS= read -r file; do echo "$file"; done < files
a strange blue cloud.txt
O incluso, si insiste en la UUoC :
$ cat files | while IFS= read -r file; do echo "$file"; done
a strange blue cloud.txt
Entonces, el whileciclo leerá su entrada y usará readpara asignar cada línea a una variable. Los IFS=conjuntos El separador de campo de entrada a NULL * , y de la -ropción de readparadas de TI de la interpretación de escapes de barra invertida (de modo que \tse trata como barra + ty no como una pestaña). El --después de que el mvmedio "tratar todo después de que el - como un argumento y no es una opción", que le permite hacer frente a los nombres de archivo que comienzan con -correctamente.
* Esto no es necesario aquí, estrictamente hablando, el único beneficio en este escenario es que evita readeliminar cualquier espacio en blanco al inicio o al final, pero es un buen hábito a tener en cuenta cuando necesita tratar con nombres de archivos que contienen caracteres de nueva línea, o en general, cuando necesita poder tratar con nombres de archivos arbitrarios.
IFS=no ayudará con las nuevas líneas en los nombres de archivo. El formato del archivo aquí simplemente no permite nombres de archivo con nuevas líneas.IFS=es necesario para los nombres de archivos que comienzan en el espacio o en la pestaña (o cualquier otro carácter que no sea el de nueva línea $ IFS contenido de antemano).lsofindcon sustituciones de comandos cuando hay formas mejores y más confiables de hacerlo.$(cat file)estaría bien cuando se hace bien. Es tan difícil "hacerlo bien" con un ciclo de lectura while como con un + $ (...). Mira mi respuesta.Que
$(cat file_list.txt)en los shells POSIX comobashen el contexto de la lista es el operador split + glob (zshsolo hace la parte dividida como cabría esperar).Se divide en caracteres de
$IFS(de forma predeterminada, SPC , TAB y NL) y se globaliza a menos que desactive el globbing por completo.Aquí, desea dividir solo en nueva línea y no desea la parte global, por lo que debería ser:
Eso también tiene la ventaja (sobre un
while readbucle) de descartar líneas vacías, preservar una línea final no terminada y preservarmvla entrada estándar (necesaria en caso de avisos, por ejemplo).Sin embargo, tiene la desventaja de que el contenido completo del archivo debe almacenarse en la memoria (varias veces con shells como
bashyzsh).Con algunos shells ( y
ksh,zshen menor medidabash), puede optimizarlo en$(<file_list.txt)lugar de hacerlo$(cat file_list.txt).Para hacer el equivalente con un
while readbucle, necesitarías:O con
bash:O con
zsh:O con GNU
mvyzsh:O con GNU
mvy GNUxargsy ksh / zsh / bash:Más información sobre lo que significa dejar las expansiones sin citar en Implicaciones de seguridad al olvidar citar una variable en bash / POSIX shells
fuente
$(cat file_list.txt)lee todo el archivo en la memoria antes de iterar, mientras quewhile read ...solo lee una línea a la vez. Esto podría ser un problema para archivos grandes.En lugar de escribir un guión, puede usar find ..
para el caso en que los archivos se encuentran en el archivo, puede hacer lo siguiente:
el segundo no estoy seguro ..
Buena suerte
fuente
find, también puede usarlofindpara todo. ¿Por qué traerloxargs?find -type f -iname '*.txt' -exec mv {} /folder/to/destination/.-execse comporta perfectamente con nombres de archivo arbitrarios (incluidos los que contienen espacios, líneas nuevas o cualquier otra rareza). Sé cómoxargsfunciona, gracias :) Simplemente no veo el punto de llamar a un comando separado cuandofindya puedo hacerlo por ti. No tiene nada de malo, simplemente ineficiente.xargstambién tiene el inconveniente de golpear stdin (quemvnecesita para sus indicaciones). También un problema con la solución de @terdon. Con GNUxargsy conchas con sustitución de procesos, se puede aliviar conxargs -0IF -a <(find...) mv F /dest#! / bin / bash
ARCHIVO =
zenity --title "Pick a Movie" --file-selectionpara ARCHIVO en "$ {ARCHIVO [0]}"
hacer omxplayer "$ {FILE [0]}" hecho
! / bin / bash
ARCHIVO =
zenity --title "Pick a Song" --file-selectionpara ARCHIVO en "$ {ARCHIVO [0]}"
jugar "$ {FILE [0]}" hecho
! / bin / bash
DIR =
zenity --title "Pick a Album" --file-selection --directorypara DIR en "$ {DIR [0]}"
haga el cd "$ {DIR [0]}" && find. -type f -name ' .ogg' -o -name ' .mp3' | sort --version-sort | mientras lee DIR; jugar "$ DIR" hecho hecho
! / bin / bash
DIR =
zenity --title "Pick a Album" --file-selection --directorypara DIR en "$ {DIR [0]}"
haga el cd "$ {DIR [0]}" && find. -type f -name ' .ogg' -o -name ' .mp3' | mientras lee DIR; jugar "$ DIR" hecho hecho
fuente