Ter o comando ls se comportando de maneira diferente com base no número de entradas

2

É possível ter o comando ls se comportando de maneira diferente com base no número de entradas de diretório que podem ser listadas?

Se eu usar apenas ls (sem opções de modificação, mas posso especificar diretórios ou filtros), quero que:

  • aplique o formato de listagem -l long se houver 10 entradas ou menos
  • mostre somente as 50 primeiras entradas e exiba um aviso de que há x more entries

Isso é possível? Como posso fazer isso?

Note que eu não quero usar um comando de script personalizado para um comando personalizado - eu estou bem com um script personalizado ou wrapper, mas eu ainda quero usar ls para fazer isso, com funcionalidade completa ainda mantida. Ou seja, não my-custom-ls , mas apenas ls para chamar o script / wrapper.

    
por ADTC 25.03.2016 / 12:11

5 respostas

4

Se você não quiser uma função de comando / wrapper de script personalizada, será necessário um comando binário personalizado. O código-fonte GNU ls está disponível, juntamente com outras implementações.

Crie sua própria versão corrigida de ls e você será definido.

Note que esta mudança de comportamento iria quebrar a conformidade POSIX.

Editar (de acordo com sua pergunta revisada):

ls() {
    if [ $(command ls "$@" | wc -l) -gt 10 ]; then
        command ls "$@" | head -50
    else
        command ls -l "$@"
    fi
}

Versão aprimorada que mostra o número de entradas restantes:

ls() {
    [ ! -t 1 ] && { command ls "$@" ; return ; }
    r=$(command ls "$@")
    lines=$(printf "%s" "$r" | wc -l)
    if [ $lines -gt 10 ]; then
        printf "%s" "$r" | head -50
        if [ $lines -gt 50 ]; then
          printf "%d more entries\n" $((lines - 50))
        fi
    else
        command ls -l "$@"
    fi
}
    
por 25.03.2016 / 12:36
0

Crie seu próprio script, por exemplo em Python, que conta os argumentos e chama ls(1) com os argumentos corretos e os propaga com more(1) para paginação conforme necessário (se a saída for para um tty).

    
por 25.03.2016 / 14:39
0

Eu não posso redefinir o próprio ls, mas você pode usar essa função para um 'ls2':

ls2 () {
  num_of_files='ls | grep "\/$" | wc -l'
  if [ "$num_of_files" -gt "10" ]; then
    ls | less
  else
    ls -l
  fi  
}

para criar um comando personalizado ls2 que use grep para procurar diretórios e, em seguida, wc (função unix word count com o número de opções de linhas) para contar quantos. Você pode alterar quantos arquivos na comparação "10". Você pode alterar o que realmente é feito alterando os comandos ls -l e / ou ls -a

Se você não estiver familiarizado com as funções bash - coloque o código em um arquivo, então chmod +x o arquivo para torná-lo executável, execute o arquivo com . the_filename e use a função com ls2

Para uma solução permanente, adicione a função ao arquivo .bashrc (e considere a criação de um arquivo originado de .bashrc para que você possa começar a adicionar mais funções em um único local e não tornar deselegante o arquivo .bashrc .

Não consigo obter menos para mostrar entradas de cada vez.

    
por 25.03.2016 / 15:15
0

Uma coisa que você pode fazer é colocar cada listagem em uma linha separada e, em seguida, usar wordcount para contar linhas e ter uma declaração if else, dependendo do número de arquivos.

files=$(ls "$@" | wc -l)
if [ $files -ge 50 ]
then
something
fi

Desculpe se não é isso que você está procurando.

    
por 25.03.2016 / 15:20
0

Aqui está minha interpretação da questão. É específico do bash, já que usa um array. Ele define uma função chamada ls (portanto, certifique-se de executar unalias ls para limpar o caminho para que ele seja executado como apenas ls ). A função cria um array dos argumentos dados (ou do conteúdo atual do diretório se nenhum argumento for dado); em seguida, conta esses elementos para determinar quais ls sinalizar para usar (menos de 10, use ls -ld ; caso contrário, use ls -d ); Se houver mais de 50 arquivos, apenas os 50 primeiros serão exibidos e uma mensagem será exibida. Eu também copiei descaradamente a ideia de Kevin / jlliagre para que a função ls se comportasse mais normalmente quando a saída não fosse para uma tela.

Isso não permite que os sinalizadores sejam passados para o% realls; coisas como -r e -a precisariam de cuidados especiais.

function ls {
  _ls_longlimit=10
  _ls_cutoff=50
  declare -a _ls_files

  [ ! -t 1 ] && { command ls "$@"; return; }
  # TODO: skip past any "-rtxyz" options
  if [ $# -eq 0 ]
  then
    _ls_files=(*)
  else
    for a in "$@"
    do
      if [ -d "$a" ]
      then
        # add "${a}/*" to array
        _ls_files+=("${a}"/*)
      else
        # add $a to array
        _ls_files+=("$a")
      fi
    done
  fi
  if [ ${#_ls_files[@]} -le $_ls_longlimit ]
  then
    command ls -ld "${_ls_files[@]}"
  else
    # -1 because arrays are 0-based
    command ls -d "${_ls_files[@]:0:_ls_cutoff - 1}"
  fi
  if [ ${#_ls_files[@]} -gt $_ls_cutoff ]
  then
    echo $((${#_ls_files[@]} - _ls_cutoff)) more entries
  fi
}
    
por 26.03.2016 / 16:27

Tags