Es contenido de un directory que ignora los enlaces simbólicos

Tengo un directory en el que me gustaría enumerar todo el contenido (files y subdirectorys) sin mostrar los enlaces simbólicos. Estoy usando utilidades de GNU en Linux. La versión ls es 8.13.

Ejemplo:

Listado completo del directory:

 ~/test$ ls -Gg total 12 drwxrwxr-x 2 4096 Jul 9 10:29 dir1 drwxrwxr-x 2 4096 Jul 9 10:29 dir2 drwxrwxr-x 2 4096 Jul 9 10:29 dir3 -rw-rw-r-- 1 0 Jul 9 10:29 file1 -rw-rw-r-- 1 0 Jul 9 10:29 file2 lrwxrwxrwx 1 5 Jul 9 10:29 link1 -> link1 lrwxrwxrwx 1 5 Jul 9 10:30 link2 -> link2 

Lo que me gustaría get

 ~/test$ ls -somthing (or bash hack) total 12 dir1 dir2 dir3 file1 file2 

NOTA: Mi principal motivación es hacer un grep recursivo (GNU grep 2.10) sin seguir enlaces simbólicos.

Para la pregunta establecida, puede usar find :

 find . -mindepth 1 ! -type l 

listrá todos los files y directorys en el directory actual o cualquier subdirectory que no sea un enlace simbólico.

mindepth 1 es solo para omitir el . input del directory actual. La carne es la combinación de -type l , que significa "es un enlace simbólico", y ! , lo que significa negar la siguiente testing. En combinación, hacen coincidir cada file que no es un enlace simbólico. Esto enumera todos los files y directorys recursivamente, pero no enlaces simbólicos.

Si solo quiere files regulares (y no directorys):

 find . -type f 

Para include solo los hijos directos de este directory, y no todos los demás recursivamente:

 find . -mindepth 1 -maxdepth 1 

Puede combinar esas testings (y otras) para get la list de files que desea.

Para ejecutar un grep en particular en cada file que coincida con las testings que está utilizando, use -exec :

 find . -type f -exec grep -H 'some pattern' '{}' + 

El '{}' se replaceá con los files. El + es necesario para indicarle que su command está hecho. La opción -H obliga a grep a mostrar un nombre de file incluso si se ejecuta con un solo file coincidente.

O, más simple:

 ls -l | grep -v ^l 

A partir de la versión 2.12 en adelante, la opción -r para grep GNU no desreference enlaces simbólicos a less que usted los especifique a mano:

-r, –recursive

Lea todos los files debajo de cada directory, recursivamente, siguiendo los enlaces simbólicos solo si están en la línea de command. Esto es equivalente a la opción -d recurse.

-R, –dereference-recursivo

Lea todos los files debajo de cada directory, recursivamente. Siga todos los enlaces simbólicos, a diferencia de -r.

En zsh, esto sería fácil gracias a los calificadores glob :

 grep PATTERN **/*(.) 

El patrón **/ atraviesa subdirectorys recursivamente. El calificador glob . restringe la coincidencia a files regulares.

Sin zsh, use find (vea la respuesta de Michael Horner ). Y en este caso particular, GNU grep puede hacer lo que usted desea (es exactamente lo que grep -r hace), pero solo desde la versión 2.12, las versiones anteriores seguían los enlaces simbólicos.

Puede usar $LS_COLORS para hacer esto. Si su versión de ls admite la especificación de los colors con esa variable, puede definir la salida por tipo de file. Es un comportamiento integrado y muy configurable. Así que creé algunos files para demostrar esto como:

 for f in 9 8 7 6 5 4 3 2 1 do touch "${f}file" && ln -s ./"${f}file" ./"${f}filelink" done 

Así que ahora lo haré:

 LS_COLORS='lc=:rc=:ec=:ln=\n\n\0HERE_THERE_BE_A_LINK>>\0:' \ ls -1 --color=always | cat ###OUTPUT### 1file HERE_THERE_BE_A_LINK>>1filelink@ 2file HERE_THERE_BE_A_LINK>>2filelink@ 3file ... HERE_THERE_BE_A_LINK>>8filelink@ 9file ... 

Y los nulos también están allí …

 LS_COLORS='lc=:rc=:ec=:ln=\n\n\0HERE_THERE_BE_A_LINK>>\0:' \ ls -1 --color=always | sed -nl 1file$ $ $ \000HERE_THERE_BE_A_LINK>>\0001filelink@$ 2file$ $ $ \000HERE_THERE_BE_A_LINK>>\0002filelink@$ 3file$ ... 

Puede especificar para todos o cualquier tipo de file. Hacerlo para un solo tipo de file puede no hacerte desear, ya que ls ha incorporado algunos valores de compilation pnetworkingeterminados para escapes de terminal. Harías mucho mejor para abordar la API como una única interfaz. Aquí hay un pequeño y sencillo método para analizar y asignar los valores pnetworkingeterminados configurados por las dircolors entorno actual:

 LS_COLORS='rs=:no=//:lc=:rc=:ec=//:'$( set -- di fi ln mh pi so do bd cd or su sg ca tw ow st ex for fc do printf %s "$fc=/$fc//:" done) ls -l --color=always | cat 

Su salida en mi directory personal se ve así:

 total 884 ///-rw-r--r-- 1 mikeserv mikeserv 793 Jul 9 11:23 /fi//1/ //drwxr-xr-x 1 mikeserv mikeserv 574 Jun 24 16:50 /di//Desktop// //-rw-r--r-- 1 mikeserv mikeserv 166 Jul 4 23:02 /fi//Terminology.log/ //-rw-r--r-- 1 mikeserv mikeserv 0 Jul 6 11:24 /fi//new file/ //lrwxrwxrwx 1 mikeserv mikeserv 10 Jul 11 04:18 /ln//new file link/ -> /fi//./new file/ //-rwxr-xr-x 1 mikeserv mikeserv 190 Jun 22 11:26 /ex//script.sh/* //-rw-r--r-- 1 mikeserv mikeserv 433568 Jun 22 17:10 /fi//shot-2014-06-22_17-10-16.jpg/ //-rw-r--r-- 1 mikeserv mikeserv 68 Jun 17 19:59 /fi//target.txt/ 

Puede ejecutar eso con cat -A también y la única diferencia que encontrará es que verá $ para líneas nuevas – no hay caracteres no imprimibles introducidos por ls --color=always con esta configuration – solo lo que ve aquí.

ls inserta sus escapes de terminal pnetworkingeterminados como este:

 ${lc}${type_code}${rc}FILENAME${lc}${rs}${rc} 

… donde los valores pnetworkingeterminados para $lc (a la izquierda del código) , $rc (a la derecha del código) y $rs (restablecer) son:

  \033 - ESCAPE m - END ESCAPE 0 - reset 

…respectivamente. ${type_code} se usa para sustituir los fi (file común – unset pnetworkingeterminado) , di (directory) , ln (enlace) y cualquier otro tipo de file que conozca. También hay $no (normal) que también está desarmado por defecto y que aquí está representado por // al comienzo de cada línea. Mi pequeño y simple bloque IFS=: funciona simplemente insertando el nombre de cada configurable también como su propio valor y agregando una barra o dos, aunque \0 bytes NUL también lo harían.

Por defecto, ls también insertá un $rs inmediatamente anterior a su primer resultado $lc , pero esto no se representa con precisión aquí. En este caso, he especificado $ec (código final) que representa $rs en todos los casos, cuando se especifica que no obtiene $rs entre $no y ${type_code} como lo haría de otra manera, solo se presenta inmediatamente después de un nombre de file y una vez al comienzo de la salida, como se puede ver en una barra oblicua al principio de la línea uno.

Aquí hay un fragment de mis propios $LS_COLORS

 printf %s "$LS_COLORS" rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:\ so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:\ or=40;31;01:su=37;41:sg=30;43:ca=30;41:\ tw=30;42:ow=34;42:st=37;44:ex=01;32:\ *.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:... 

Y, en verdad, mi pequeño hack de shell es probablemente demasiado complicado: hay una interfaz ampliamente disponible para asignar estos valores. Pruebe dircolors -p en su cli e info dircolors para get más información al respecto.

Puede envolver los nombres de file en cadenas arbitrarias. Puede comentarlos si lo desea. Puede especificar comportamientos similares basados ​​solo en la extensión de file. Realmente no hay muchas cosas que no puedas especificar de esa manera.

Ahora tampoco estoy haciendo todo esto: lo supe después de tropezar con el código fuente por crash.

Con esta configuration particular, ls emitirá:

  1. $no – una vez por logging al inicio de cada logging

  2. ${type_code} – una vez inmediatamente anterior a cada nombre de file para include una abreviatura del tipo del file y siempre en la misma línea y 7 campos delimitados en blanco después de $no o inmediatamente después de un -> denota el objective de un enlace simbólico.

  3. $ec – una vez inmediatamente antes de la primera línea y luego solo una vez inmediatamente después de cada nombre de file.

  4. Todos los otros valores están vacíos.

Lo que sigue es un ls nulo-delimitado, y esta vez cat -A , sin embargo, sin él, se vería igual que el último ejemplo:

 LS_COLORS='rs=:no=\0//:lc=:rc=:ec=\0//:'$( set -- di fi ln mh pi so do bd cd or su sg ca tw ow st ex for fc do printf %s "$fc=/$fc//\0:" done) ls -l --color=always | cat -A total 884$ ^@//^@//-rw-r--r-- 1 mikeserv mikeserv 793 Jul 9 11:23 /fi//^@1^@//$ ^@//drwxr-xr-x 1 mikeserv mikeserv 574 Jun 24 16:50 /di//^@Desktop^@///$ ^@//-rw-r--r-- 1 mikeserv mikeserv 166 Jul 4 23:02 /fi//^@Terminology.log^@//$ ^@//-rw-r--r-- 1 mikeserv mikeserv 0 Jul 6 11:24 /fi//^@new$ file^@//$ ^@//lrwxrwxrwx 1 mikeserv mikeserv 10 Jul 11 04:18 /ln//^@new$ file$ link^@// -> /fi//^@./new$ file^@//$ ^@//-rwxr-xr-x 1 mikeserv mikeserv 190 Jun 22 11:26 /ex//^@script.sh^@//*$ ^@//-rw-r--r-- 1 mikeserv mikeserv 433568 Jun 22 17:10 /fi//^@shot-2014-06-22_17-10-16.jpg^@//$ ^@//-rw-r--r-- 1 mikeserv mikeserv 68 Jun 17 19:59 /fi//^@target.txt^@//$ 

Y para eliminar de manera confiable todos los enlaces simbólicos de un listdo como este, puede hacer un cambio simple:

 LS_COLORS='rs=:no=//:lc=:rc=:ec=/ :'$( set -- di fi mh pi so do bd cd or su sg ca tw ow st ex for fc do printf %s "$fc=$fc/:" done)ln=///: ls -l --color=always | sed ':ln \|///|{N;\|\n//|!bln};s|.*//||' 

Mis resultados después de ejecutar eso se ven como …

 total 884 -rw-r--r-- 1 mikeserv mikeserv 793 Jul 9 11:23 fi/1/ drwxr-xr-x 1 mikeserv mikeserv 574 Jun 24 16:50 di/Desktop/ / -rw-r--r-- 1 mikeserv mikeserv 166 Jul 4 23:02 fi/Terminology.log/ -rw-r--r-- 1 mikeserv mikeserv 0 Jul 6 11:24 fi/new file/ -rwxr-xr-x 1 mikeserv mikeserv 190 Jun 22 11:26 ex/script.sh/ * -rw-r--r-- 1 mikeserv mikeserv 433568 Jun 22 17:10 fi/shot-2014-06-22_17-10-16.jpg/ -rw-r--r-- 1 mikeserv mikeserv 68 Jun 17 19:59 fi/target.txt/ 

Usando algún command como el que hago arriba:

 LSCOLORS=...$(...)fc1=///:fc2=///: ls ... | sed ... 

(donde fc1 y fc2 son types de files enumerados después del set -- en la subshell) deberían servir para eliminar de manera confiable cualquier combinación de types de files que pueda desear desde su salida, independientemente de los caracteres que los nombres de file puedan contener.

Prueba este:

 ls | grep -v " -> " 

Pruebe este command: ls -p | grep -v @ ls -p | grep -v @