2009-08-21 6 views
15

empecé con esto:¿Cómo hacer algo con cada archivo en un directorio usando bash?

command * 

Pero esto no funciona cuando el directorio está vacío; el * comodín se convierte en un carácter literal "*". Así que cambié a esto:

for i in *; do 
    ... 
done 

que funciona, pero una vez más, no si el directorio está vacío. Me recurrido al uso de ls:

for i in `ls -A` 

pero, por supuesto, a continuación, los nombres de archivo con espacios en ellos separarnos. He intentado virar en el interruptor -Q:

for i in `ls -AQ` 

que hace que los nombres que todavía puede dividir, sólo con un carácter de comillas al principio y al final de su nombre. ¿Me estoy perdiendo algo obvio aquí, o es más difícil de lo que debería ser?

+0

nombres de archivos de Windows estúpidos con espacios! Voy a ser martillado (abajo votado) para esto, pero ...Mi consejo para los compañeros de trabajo con respecto a las secuencias de comandos: tan pronto como su script tenga "si" o "mientras", es hora de dejar de lado "shell", y recoger "perl" :-(estoy seguro de que hay alguna forma masoquista de hacer esto trabajo, pero ay. Por cierto, la solución find -exec de Bombe necesita limitar la profundidad, por lo que los subdirectorios tampoco se recogen. – Roboprog

Respuesta

35

Suponiendo que sólo desea hacer algo para archivos, la solución es sencilla para comprobar si $ i es un archivo:

for i in * 
do 
    if test -f "$i" 
    then 
     echo "Doing somthing to $i" 
    fi 
done 

realmente debería siempre hacer este tipo de pruebas, ya que es casi seguro que no quiere para tratar archivos y directorios de la misma manera. Tenga en cuenta las comillas alrededor de "$ i" que evitan problemas con los nombres de archivo que contienen espacios.

+1

Parece la respuesta más simple. Es extraño que tantas guías de scripts de shell siempre te indiquen utilizar *, pero no siempre menciona el comportamiento literal "*" cuando no hay archivos en el CWD. –

11

find podría ser lo que quieras.

find . | while read file; do 
    # do something with $file 
done 

O tal como esto:

find . -exec <command> {} \; 

Si no desea que la búsqueda para incluir subdirectorios que pueda necesitar para agregar una combinación de -type f y -maxdepth 1 que el comando find. Vea el find man page para más detalles.

+4

Beneficio adicional de no interrumpir cuando tienes más de 10.000 archivos en un directorio. – MSalters

+0

@MSalters ¿Quién tiene tantos? La última vez que tuve tantos fue cuando olvidé que un programa dividido esperaba bytes y no una cantidad de archivos divididos ... –

+2

Ocurre todo el tiempo y con más frecuencia de lo que piensas. – Bombe

2

esto debe hacer el truco:

find -type d -print0 | xargs -n 1 -0 echo "your folder: {} !" 
find -type f -print0 | xargs -n 1 -0 echo "your file: {} !" 

la print0/0 están ahí para evitar problemas con los espacios en blanco

+1

estás realmente mejor usando find -type d -exec eco "su carpeta: {}" \; ... xargs se topa con problemas si su ruta es demasiado profunda. –

8

Depende de si usted va a escribir esto en un símbolo del sistema y la que comandar estás aplicando a los archivos.

Si se tipea puede elegir su segunda opción y sustituirla por algo inofensivo. Me gusta usar echo en lugar de mv o rm, por ejemplo.

poner todo en una línea:

for i in * ; do command $i; done 

Cuando eso funciona - o usted puede ver donde se produce un error, y si es inofensivo, puede pulsar la flecha hacia arriba, editar el comando y vuelva a intentarlo.

5

Uso shopt para prevenir la expansión de * .txt

shopt -s nullglob 
for myfile in *.txt 
do 
    # your code here 
    echo $myfile 

done 
Cuestiones relacionadas