Mi mejor apuesta actual es:
for i in $(find . -name *.jpg); do echo $i; done
Problema: no maneja espacios en los nombres de archivo.
Nota: También me encantaría una forma gráfica de hacerlo, como el comando "árbol".
Mi mejor apuesta actual es:
for i in $(find . -name *.jpg); do echo $i; done
Problema: no maneja espacios en los nombres de archivo.
Nota: También me encantaría una forma gráfica de hacerlo, como el comando "árbol".
Respuestas:
La forma canónica es hacer
find . -name '*.jpg' -exec echo {} \;
(reemplazar \;
con +
para pasar más de un archivo a la echo
vez)
o (específico de GNU, aunque ahora algunos BSD también lo tienen):
find . -name '*.jpg' -print0 | xargs -r0 echo
zsh:
for i (**/*.jpg(D)) echo $i
echo
que expande secuencias de escape como \b
(al menos las Unix conforme echo
).
find
manual se muestra find . -type f -exec file '{}' \;
en la EXAMPLES
sección. Tal vez algunas conchas tratarán los frenos especialmente.
'{}'
, \{\}
, {}
, "{}"
, '{'}
se expanden por el shell (lo Bourne-como la cáscara) para un argumento para encontrar que son los dos caracteres "{" y "}". Reemplace "buscar" con "buscar eco", o printf '<%s>\n' find
si desea verificar dos veces.
Ya se han dado mejores respuestas.
Pero tenga en cuenta que los espacios no son el único problema en el código que proporcionó. los caracteres de tabulación, nueva línea y comodín también son un problema.
Con
IFS='
'
set -f
for i in $(find . -name '*.jpg'); do echo "$i"; done
Entonces solo los caracteres de nueva línea son un problema.
Lo que ha mencionado es uno de los problemas básicos que enfrentan las personas cuando intentan leer los nombres de los archivos. A veces, las personas con conocimientos limitados y que tienen una idea errónea de la estructura de archivos y carpetas tienden a olvidar que " en UNIX Todo es un archivo ". Por lo tanto, no entienden que también necesitan manejar espacios, ya que el nombre del archivo puede consistir en 2 o más palabras con espacios.
Solución: Entonces, una de las formas más conocidas de hacer esto es hacer una lectura limpia .
Aquí leeremos todos los archivos presentes y los mantendremos en una variable, la próxima vez que realicemos el procesamiento deseado solo tendremos que mantener esa variable entre comillas, lo que preservará los nombres de los archivos con espacios. Esta es una de las formas básicas de hacerlo, sin embargo, las otras respuestas proporcionadas por las otras personas aquí funcionan igual de bien.
SCRIPT:
find /path/to/files/ -iname "*jpg" | \
while read I; do
cp -v --parent "$I" /backup/dir/
done
Aquí estoy leyendo los archivos dándoles la ruta y, lo que sea que esté leyendo, los mantengo dentro de una variable I, que citaré en un momento posterior mientras lo proceso para preservar los espacios para procesarlo correctamente.
Espero que esto te ayude de alguna manera.
Simplemente con find
y bash
:
find . -name '*.jpg' -exec bash -c '
echo "treating file $1 in bash, from path : ${1%/*}"
' -- {} \;
De esta manera, usamos $1
en bash, como en un script básico, que abre buenas perspectivas para realizar cualquier tarea avanzada (o no).
Una forma más eficiente (para evitar tener que iniciar un nuevo bash para cada archivo):
find . -name '*.jpg' -exec bash -c 'for i do
echo "treating file $i in bash, from path : ${i%/*}"
done' -- {} +
En la versión reciente de bash, puede usar la globstar
opción:
shopt -s globstar
for file in **/*.jpg ; do
echo "$file"
done
Para acciones simples, incluso puede omitir el bucle por completo:
echo **/*.jpg
set -G
), que no se debe utilizar en bash como la versión de bash se divide fundamentalmente (como GNU grep -r
) a medida que desciende en enlaces simbólicos a directorios (equivalente a find -L
o del zsh ***/*.jpg
) También tenga en cuenta que, al contrario de encontrar, omitirá los archivos de puntos y no descenderá a los dotdirs (por defecto).
$i
? Hago eso y funciona bien. ¿Hay algo malo con ese enfoque?