2012-03-07 8 views
11

Tengo los siguientes comandos. Dondequiera que esté presente el archivo .user.log, debemos imprimir los directorios principales (es decir, hht y wee1). ¿Cómo se puede hacer esto?Buscar archivos e imprimir solo sus directorios principales

$ cd /nfs//office/ && find . -name '.user.log' 
./hht/info/.user.log 
./wee1/info/.user.log 

Respuesta

11

Me falta algo aquí. Seguramente toda esta expresión regular y/o looping no es necesaria, un one-liner hará el trabajo. También fallarán las soluciones "for foo in $()" cuando haya espacios en los nombres de ruta.

sólo tiene que utilizar nombredir dos veces con xargs, para obtener los padres de los padres ...

# make test case 
mkdir -p /nfs/office/hht/info 
mkdir -p /nfs/office/wee1/info 
touch /nfs/office/hht/info/.user.log 
touch /nfs/office/wee1/info/.user.log 

# parent's parent approach 
cd /nfs//office/ && find . -name '.user.log' | xargs -I{} dirname {} | xargs -I{} dirname {} 

# alternative, have find print parent directory, so dirname only needed once... 
cd /nfs//office/ && find . -name ".user.log" -printf "%h\n" | xargs -I{} dirname {} 

Produce

./hht 
./wee1 
+0

Y puedo hacer ll para encontrar las permisecciones del directorio encontrado resultante. -name '.user_repo.log '| xargs -i {} dirname {} | xargs -i {} dirname {} | xargs ll – Rajeev

+0

Suponiendo que el ll al que se refiere es el alias comúnmente utilizado para "ls -lA", entonces no. xargs solo ejecutará comandos, no alias. Sin embargo, puede hacer "xargs ls-lA" en su lugar ... – Adam

+0

Tenga cuidado, la bandera '-i' para' xargs' aparece como obsoleta, preferiblemente use la bandera '-I'. –

3
for file in $(find /nfs/office -name .user.log -print) 
do 
    parent=$(dirname $(dirname $file)) 
    echo $parent 
done 

EDIT: Lo siento perdido que desea que el directorio de los abuelos.

0
find /nfs/office -name '.user.log' | while read line 
do 
    echo $line | awk -F/ '{print $(NF-1),$NF}' 
done 
0

se podría hacer algo como esto:

cd /nfs/office/ && find . -name '.user.log' | xargs -n1 -I{} expr match {} '\(\.\(\/[^/]*\/\)\?\)' 

donde el xargs utiliza expr match para extraer la parte que comienza con . hasta que el primer partido de directorios entre caracteres de barra (/dir/).

Una versión alternativa utilizando sed sería la siguiente:

cd /nfs/office/ && find . -name 'file.txt' | sed -r 's|(\./([^/]*/)?).*|\1|' 
1

@trojanfoe tiene la idea correcta; this es sólo una manera de conseguir que funcione de manera segura con cualquier nombre del archivo, y casi cualquier comando dentro del bucle:

while IFS= read -r -d '' -u 9 
do 
    echo "$(dirname -- "$(dirname -- "$REPLY")")" 
done 9< <(find "/nfs/office/" -name '.user.log' -print0) 

Si usted quiere que el eco sólo los únicas nombres:

while IFS= read -r -d '' -u 9 
do 
    echo "$(dirname -- "$(dirname -- "$REPLY")")" 
done 9< <(find "/nfs/office/" -name '.user.log' -print0) | sort -u 
+0

¿Alguna razón en particular está utilizando un descriptor de archivo diferente? –

+0

En caso de que quiera hacer algo con stdin dentro del ciclo. Se explica en el enlace de arriba. – l0b0

2

Usted puede hacer esto fácilmente con las opciones de formato de la acción de -printffind (ver man find).

cd /nfs//office/ && find . -name '.user.log' -printf "%h\n" 
./hht/info 
./wee1/info 

Desde el man page:

Screenshot of find manpage

%h\n imprimirá ruta para cada archivo en una nueva línea.

Tenga en cuenta que -printf es solo de GNU. No funcionará en macOS (un sistema BSD).

0
find -type f -exec bash -c 'echo "${1%/*}"' bash {} \; 
Cuestiones relacionadas