Classifique a saída de find -exec ls


14

É possível a saída find … -exec ls -ls ;ordenada alfabeticamente, por nome de arquivo?

Este é o meu comando cron:

find /home/setefgge/public_html -type f -ctime -1 -exec ls -ls {} \;

Este comando funciona bem, na maior parte. Mas os resultados não são classificados em nenhuma sequência significativa. Seria muito útil se eles fossem classificados pelo campo de nome do arquivo.


1
Usando o zsh? ls -ls **/*(.)
Kevin

@ Kevin Não é bem assim - lsiria classificar.
Gilles 'SO- stop be evil'

Respostas:


14

Presumo que seus nomes de arquivos não contenham novas linhas.

find /home/setefgge/public_html -type f -ctime -1 -exec ls -nls {} + | sort -k 10

Usar em +vez de ;para finalizar a -execação a torna mais rápida, agrupando as chamadas de ls. Você pode classificar através do sortcomando; diga para começar a classificar no 10º campo (os 9 primeiros são os metadados: blocos, permissões, contagem de links, usuário, grupo, tamanho e 3 campos de data / hora). A opção -ninforma lspara usar valores numéricos para o usuário e grupo, o que evita o risco de nomes de usuários ou grupos que contenham espaços em branco.

Como alternativa, com o zsh, você pode sair sem assumir nenhum nome usando qualificadores glob para coletar e classificar os arquivos e zargsexecutar lsvárias vezes se a linha de comando for muito longa. Você precisa do GNU ls(especificamente sua -fopção) para evitar a re-classificação ls(outra abordagem seria emular lscom o zsh zstat).

autoload -U zargs
zargs -- /home/setefgge/public_html/**/*(.c-2) -- ls -lnsf

Muito obrigado! O uso do primeiro comando que você enviou faz a classificação. O número ainda seria 10 se eu usasse um caminho mais curto? Por exemplo, se eu executar o mesmo comando em / home / setefgge em vez de em public_html?
MAJ

@MaJ 10 é o número de campos ignorados, não tem nada a ver com o tamanho do nome do arquivo.
Gilles 'SO- stop be evil'

Obrigado. Agradeço sua ajuda e também a ajuda de todos os demais. Eu considero esse problema resolvido. Meu comando cron agora está classificando os arquivos. Esta é a primeira vez que enviei uma pergunta ao Stackexchange. Não vejo a opção "Resolvido". Se algum de vocês souber como postar isso como resolvido, vá em frente e faça isso. Obrigado!
MAJ

@MaJ A coisa mais próxima de marcar uma pergunta como resolvida é marcar uma das respostas como aceita. Somente você, o solicitante, pode fazê-lo. Para fazer isso, clique na marca de seleção ao lado da resposta que mais lhe ajudou. Se você aceitar uma resposta, receberá mais 2 pontos de reputação e, depois disso, poderá votar novamente nas postagens; você pode votar todas as postagens que achou úteis. Para obter mais informações, consulte a página do tour e a página de ajuda sobre o que fazer quando alguém responder à sua pergunta .
Gilles 'SO- stop be evil'

1

Por que não canalizar o resultado da busca através da classificação e depois executar ls para cada uma das linhas?

find . -type f -ctime -1 | sort | while IFS= read -r filename; do ls -ls "$filename"; done

1

O POSIX tem a dizer sobre datas em uma ls -llistagem ong:

O <date and time>campo deve conter a data e o carimbo de data e hora apropriados de quando o arquivo foi modificado pela última vez. No código do idioma POSIX, o campo deve ser equivalente à saída do seguinte comando date:

date "+%b %e %H:%M"

... se o arquivo foi modificado nos últimos seis meses ou:

date "+%b %e %Y"

Levando isso em consideração e assegurando que, se houver novas linhas em um nome de arquivo, elas sejam devidamente preenchidas com a ls -qopção também especificada no POSIX , é relativamente fácil preparar uma regex para um lsresultado sem find:

d=$(date "+%b %e") y=$(date --date=yesterday "+%b %e")
echo "$d" "$y"

###OUTPUT###
Jul  5 Jul  4

greppara isso e você retornará apenas linhas que contenham as seqüências que representam as datas de hoje ou de ontem. O seguinte comando adiciona um pouco a isso:

ls -alRcq | sed "1H;/^-/!{/./d;N;h};/$d\|$y/!d;x;/\n/p;g"

ls opções consistem em:

  1. -a retornar todos os arquivos em um diretório - incluindo aqueles que começam com um .dot
  2. -l lista longa
  3. -R listar recursivamente todos os diretórios filhos
  4. -c tempo de modificação da tela em vez do tempo de acesso
  5. -qretorna o shell glob em ?vez de caracteres não imprimíveis ou \tab em um nome de arquivo

Esses resultados são passados ​​sobre o |pipearquivo ao sedqual corresponde apenas:

  1. A linha em branco que precede o nome do caminho e a seguinte linha
  2. Linhas começando com - (em outras palavras - não dpara diretório) que também contêm o seu date.
  3. No entanto, ele não imprime as linhas do nome do caminho, a menos que o diretório que eles nomeiem contenha arquivos para os quais você filtrou.

A saída é assim:

ls -alRcq --color=always | 
sed "1H;/^-/!{/./d;N;h};/$d\|$y/!d;x;/\n/p;g"

###OUTPUT###
.:
-rw------- 1 mikeserv mikeserv   2086 Jul  4 10:52 .bash_history
-rw------- 1 mikeserv mikeserv   2657 Jul  4 15:20 .lesshst
-rw-r--r-- 1 mikeserv mikeserv    681 Jul  5 05:18 .zdirs
-rw------- 1 mikeserv mikeserv 750583 Jul  5 08:28 .zsh_history
-rw-r--r-- 1 mikeserv mikeserv    166 Jul  4 23:02 Terminology.log
-rw-r--r-- 1 mikeserv mikeserv 433568 Jul  4 13:34 shot-2014-06-22_17-10-16.jpg
-rw-r--r-- 1 mikeserv mikeserv 445192 Jul  4 13:34 shot-2014-06-22_17-11-06.jpg

./.cache/efreet:
-rw------- 1 mikeserv mikeserv  37325 Jul  4 22:51 desktop_localhost_C.eet
-rw------- 1 mikeserv mikeserv  37325 Jul  4 23:30 desktop_localhost_en_US.eet
-rw------- 1 mikeserv mikeserv  24090 Jul  4 22:51 desktop_util_localhost_C.eet
-rw------- 1 mikeserv mikeserv  24090 Jul  4 23:30 desktop_util_localhost_en_US.eet
-rw------- 1 mikeserv mikeserv  16037 Jul  4 23:30 icon_themes_localhost.eet
-rw------- 1 mikeserv mikeserv   3117 Jul  4 23:30 icons___efreet_fallback_localhost.eet
-rw------- 1 mikeserv mikeserv 768039 Jul  4 23:30 icons_gnome_localhost.eet
-rw------- 1 mikeserv mikeserv  18589 Jul  4 23:30 icons_hicolor_localhost.eet

./.config:
-rw-r--r-- 1 mikeserv mikeserv   30 Jul  4 19:10 pavucontrol.ini

./.config/chrome:
-rw-r--r-- 1 mikeserv mikeserv 94332179 Jul  4 13:36 conf.tar.lz4.bak

Sim, ele ainda funciona com LS_COLORS- o que provavelmente é uma baixa prioridade para o seu croncurso, mas, ei, suas opções estão abertas.

De qualquer forma, isso oferece algumas vantagens significativas em relação a outras soluções possíveis.

  1. Em primeiro lugar, o find+ lsenvolve várias invocações - isso envolve apenas um único lsprocesso, e é por isso que ele é capaz de classificar tudo de maneira confiável - o que faz por padrão - e sorttambém é tornado auxiliar.

  2. Qualquer solução que envolva finde sorte lsestá praticamente fazendo tudo do trabalho duas vezes. lse findambos resolverão todos os nomes de caminhos e statarquivos. lse sortambos classificarão todos os resultados. Provavelmente é melhor usar apenas o single ls.

  3. Então, naturalmente, há o datee sedpartes desta resposta. O importante é notar que você faz a parte mais difícil e obtém o regex primeiro - e apenas uma vez - e depois remove apenas uma única lista de resultados, em vez de dizer, obter resultados, obter resultados, classificar resultados e classificar resultados.

  4. Isso não quebra nos nomes de arquivos que contêm novas linhas, como provavelmente outras soluções. Essa solução tem suas próprias advertências - que explico a seguir -, mas são minuciosas e fáceis de manusear. Na minha opinião, esta é a solução mais robusta aqui.

Há dois casos em que o comando acima pode causar problemas. O primeiro envolve os ?globs nos nomes de arquivos - enquanto já é uma solução mais robusta do que qualquer outro oferecido aqui, e a probabilidade de você encontrar um ?é pequena o suficiente por si só, existe a possibilidade de resolver esses globs pode corresponder a mais de um nome de arquivo. Por favor, veja isto para mais informações sobre este assunto.

A outra possibilidade envolve um falso positivo - por exemplo, se você tiver um nome de arquivo que realmente corresponda à datestring pela qual estamos pesquisando, grepmas que não foi realmente modificada em nenhum desses dias. Não estou contando que isso seja um problema, mas, se for, pergunte sobre isso e provavelmente posso ajudá-lo a tornar o regex mais específico para lidar com isso.


0

Você pode realmente usar uma combinação de find, xargs e ls.

Aqui está um comando de amostra: find . -type f -print0 | xargs -0 ls -lt

  • find procurará recursivamente todos os arquivos no diretório atual.
  • O xargs passará essa lista de arquivos para o lscomando em uma única chamada (desde que findretorne menos que os ARG_MAXarquivos).
  • ls -lt classificará esses arquivos por hora e formatará a saída

Para recuperar seu sistema, ARG_MAXvocê pode digitar:

$ getconf ARG_MAX
> 2621440

-1
ls -l $(find /home/setefgge/public_html -type f -ctime -1 | sort)

1
lsfaz sua própria classificação, assim canalizando a saída do findmeio sorté inútil. Além disso, seu comando gerencia nomes de arquivos que contêm espaços em branco (entre outros) e falhará se houver muitos nomes de arquivos.
Gilles 'SO- stop be evil'
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.