ls conteúdo de um diretório ignorando links simbólicos

14

Eu tenho um diretório no qual gostaria de listar todo o conteúdo (arquivos e subdiretórios) sem mostrar os links simbólicos. Eu estou usando utilitários GNU no Linux. A versão ls é 8.13.

Exemplo:

Lista completa de diretórios:

~/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

O que eu gostaria de ter

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

NOTA: Minha principal motivação é fazer um grep recursivo (GNU grep 2.10) sem seguir links simbólicos.

    
por TheMeaningfulEngineer 09.07.2014 / 10:36

8 respostas

26

Para a pergunta indicada, você pode usar find :

find . -mindepth 1 ! -type l

listará todos os arquivos e diretórios no diretório atual ou em quaisquer subdiretórios que não sejam links simbólicos.

mindepth 1 é apenas para ignorar a entrada do diretório . current. A carne dele é a combinação de -type l , que significa "é um link simbólico", e ! , o que significa negar o teste a seguir. Em combinação, eles correspondem a todos os arquivos que não são links simbólicos. Isso lista todos os arquivos e diretórios de forma recursiva, mas sem links simbólicos.

Se você quer apenas arquivos regulares (e não diretórios):

find . -type f

Para incluir apenas os filhos diretos desse diretório e não todos os outros de forma recursiva:

find . -mindepth 1 -maxdepth 1

Você pode combinar esses (e outros) testes para obter a lista de arquivos que deseja.

Para executar um determinado grep em cada arquivo que corresponda aos testes que você está usando, use -exec :

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

O '{}' será substituído pelos arquivos. O + é necessário para informar find do seu comando. A opção -H força o grep a exibir um nome de arquivo, mesmo se ele for executado com um único arquivo correspondente.

    
por 09.07.2014 / 10:48
13

Ou mais simples:

ls -l | grep -v ^l

Explicação

ls -l significa listar em formato longo . Quando você faz isso, a primeira seqüência de caracteres fornece informações sobre cada arquivo. O primeiro caractere indica o tipo de arquivo. Se for um symlink, então um l é o primeiro caractere.

grep -v ^l significa filtrar ( -v ) as linhas que começam com ( ^ ) e l .

    
por 02.02.2015 / 09:48
7

A partir da versão 2.12, a opção -r do GNU grep não desrefere os links simbólicos, a menos que você os especifique manualmente:

-r, --recursive

Read all files under each directory, recursively, following symbolic links only if they are on the command line. This is equivalent to the -d recurse option.

-R, --dereference-recursive

Read all files under each directory, recursively. Follow all symbolic links, unlike -r.

    
por 09.07.2014 / 10:40
5

Em zsh, isso seria fácil graças aos qualificadores da glob :

grep -- PATTERN **/*(.)

O padrão **/ atravessa subdiretórios recursivamente. O qualificador de glob . restringe a correspondência a arquivos regulares.

Sem zsh, use find (veja resposta de Michael Horner ). E neste caso particular, o GNU grep pode fazer o que você quer (é exatamente o que o grep -r faz) - mas somente desde a versão 2.12, as versões anteriores seguiam links simbólicos.

    
por 10.07.2014 / 23:07
2

Você pode usar $LS_COLORS para fazer isso. Se a sua versão de ls suportar a especificação das cores usando essa variável, você poderá definir a saída por tipo de arquivo. É um comportamento interno e muito configurável. Então eu criei alguns arquivos para demonstrar isso como:

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

Então, agora eu farei:

LS_COLORS='lc=:rc=:ec=:ln=\n\n
LS_COLORS='lc=:rc=:ec=:ln=\n\n
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
HERE_THERE_BE_A_LINK>>
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/
:' \ ls -1 --color=always | sed -n l 1file$ $ $
${lc}${type_code}${rc}FILENAME${lc}${rs}${rc}
0HERE_THERE_BE_A_LINK>>
 3 - ESCAPE
 m - END ESCAPE
 0 - reset 
01filelink@$ 2file$ $ $
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:...
0HERE_THERE_BE_A_LINK>>
LS_COLORS='rs=:no=
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|.*//||'
//:lc=:rc=:ec=
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/ 
//:'$( 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//
LSCOLORS=...$(...)fc1=///:fc2=///: ls ... | sed ...
:" 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^@//$
02filelink@$ 3file$ ...
HERE_THERE_BE_A_LINK>>
for f in 9 8 7 6 5 4 3 2 1
    do touch "${f}file" && 
    ln -s ./"${f}file" ./"${f}filelink"
done
:' \ 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 ...

E os nulos também estão lá ...

LS_COLORS='lc=:rc=:ec=:ln=\n\n
LS_COLORS='lc=:rc=:ec=:ln=\n\n
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
HERE_THERE_BE_A_LINK>>
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/
:' \ ls -1 --color=always | sed -n l 1file$ $ $
${lc}${type_code}${rc}FILENAME${lc}${rs}${rc}
0HERE_THERE_BE_A_LINK>>
 3 - ESCAPE
 m - END ESCAPE
 0 - reset 
01filelink@$ 2file$ $ $
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:...
0HERE_THERE_BE_A_LINK>>
LS_COLORS='rs=:no=
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|.*//||'
//:lc=:rc=:ec=
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/ 
//:'$( 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//
LSCOLORS=...$(...)fc1=///:fc2=///: ls ... | sed ...
:" 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^@//$
02filelink@$ 3file$ ...
HERE_THERE_BE_A_LINK>>%pre%:' \ 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 ...

Você pode especificar para todos ou quaisquer tipos de arquivos. Fazer isso apenas para um único tipo de arquivo pode não ser desejado, já que ls incorporou alguns valores de compilação padrão para escapes de terminal. Você faria muito melhor para endereçar a API como uma interface única. Aqui está um pequeno meio simples de analisar e atribuir padrões atuais do dircolors configurado:

%pre%

Sua saída em meu diretório inicial é assim:

%pre%

Você pode executar isso com cat -A também e a única diferença que você encontrará é que você verá $ para novas linhas - não há caracteres não imprimíveis introduzidos por ls --color=always com essa configuração - apenas o que você vê aqui.

ls insere seus escapes de terminal padrão assim:

%pre%

... onde os valores padrão para $lc (à esquerda do código) , $rc (à direita do código) e $rs (reset) são:

%pre%

... respectivamente. ${type_code} é usado para substituir os vários fi (arquivo normal - padrão não definido), , di (diretório) , ln ( link) , e todos os outros tipos de arquivos que eu conheço. Há também $no (normal) que também é por default unset e que é aqui representado por // no início de cada linha. Meu simples bloco IFS=: funciona apenas inserindo o nome para cada configurável como também seu próprio valor e adicionando uma barra ou dois - embora ls NUL bytes também funcionem.

Por padrão, $rs também inserirá um $lc imediatamente antes de sua primeira saída $ec - mas isso não é representado com precisão aqui. Neste caso, eu especifiquei $rs (end code) que significa $rs em todos os casos - quando é especificado, você não recebe um $no extra entre ${type_code} e $LS_COLORS como você faria de outra forma - ele só é apresentado imediatamente após um nome de arquivo e uma vez no início da saída - como você pode ver na barra extra na primeira linha.

Aqui está um trecho do meu próprio dircolors -p

%pre%

E, na verdade, meu pequeno hack de shell é provavelmente muito complicado - há uma interface amplamente disponível para atribuir esses valores. Experimente info dircolors em seu cli e ls para mais informações sobre isso.

Você pode envolver os nomes dos arquivos em sequências arbitrárias. Você pode comentá-los, se desejar. Você pode especificar comportamentos semelhantes com base apenas na extensão do arquivo. Não há muita coisa que você não possa especificar dessa maneira.

Agora, eu não estou apenas inventando tudo isso - aprendi sobre isso depois de encontrar o código-fonte por acidente.

Com essa configuração específica, $no será emitido:

  1. ${type_code} - uma vez por registro no início de cada registro

  2. $no - uma vez precedendo cada nome de arquivo para incluir uma abreviação do tipo do arquivo e sempre ocorrendo na mesma linha e 7 campos delimitados por espaço em branco após -> ou imediatamente após um $ec denotando o destino de um link simbólico.

  3. ls - uma vez imediatamente antes da primeira linha e, posteriormente, apenas uma vez imediatamente após cada nome de arquivo.

  4. Todos os outros valores estão vazios.

O que segue é um cat -A delimitado por nulo e, desta vez, usarei -l , mas sem ele pareceria o mesmo que o último exemplo:

%pre%

Assim, para remover com segurança os todos links simbólicos de uma listagem de fc1 ong como essa, você pode fazer uma alteração simples:

%pre%

Meus resultados depois de executados parecem ...

%pre%

Usando algum comando como o que eu faço acima:

%pre%

... (onde fc2 e set -- são tipos de arquivos listados após ls no subshell) deve servir para remover com segurança quaisquer combinações de tipos de arquivos que você possa desejar de %code% output independentemente de qualquer caractere que os nomes de arquivos possam conter.

    
por 10.07.2014 / 23:47
0

A resposta acima levou ao seguinte:

 ls -1F | grep -i "/"

Curiosamente, deixar o comando 1 do ls ainda fornece uma lista.

    
por 22.06.2018 / 17:56
-2

Tente este:

ls | grep -v " -> "
    
por 09.07.2014 / 12:55
-3

Experimente este comando: ls -p | grep -v @

    
por 09.07.2014 / 10:46