Existe uma substituição de “ls” que possa lidar com curingas?

0

Acabei de aprender que o ls não pode manipular curingas ( ls '*' não funciona) e, portanto, o shell faz isso antes que o ls seja invocado. Então o comportamento de ls pode ser considerado logicamente para pessoas que trabalham 20 anos com unix, para mim não é e eu não mantenho com ls.

Eu quero um comando de diretório que procure por arquivos e diretórios e depois aplique o filtro curinga. Então, um ls cr* não lista arquivos dentro do diretório "cron.daily".

Eu sei que existe ls -d e fiz um alias lx=ls -lartd . Mas então eu reconheci que ls -d sem qualquer argumento por alguma razão secreta não funciona de forma alguma.

Existe algum substituto que eu possa instalar?

    
por jms 17.06.2016 / 00:52

4 respostas

5

Você pode usar find , que (em muitas plataformas) possui uma opção -ls . Então você poderia fazer

find . -maxdepth 1  -name '*' -ls

Mas, se for difícil lembrar de ls -d , talvez você não encontre find de melhoria.

    
por 17.06.2016 / 00:56
1

Se o que você deseja é um comando cmd , de modo que cmd cr* liste cron.daily em si, esse comando será ls -d . Se houver muita digitação, você pode definir um alias . Por exemplo, coloque esta linha no seu ~/.bashrc :

alias l='ls -d'

Em seguida, executar l cr* exibirá informações sobre cron.daily , enquanto ls cr* listará o conteúdo do diretório cron.daily (e de qualquer outro diretório que corresponda ao padrão e a qualquer outro diretório que não corresponda ao padrão) .

ls -d funciona. Ele faz exatamente o que você pediu: ele lista o diretório atual. Isso pode não ser muito útil - ls -ld é um pouco útil, mas não ls -d - mas os computadores fazem o que você manda, eles não lêem a sua opinião para descobrir o que você quer.

Se o que você quer é obter o efeito de ls -d , exceto que sem argumentos você recebe uma listagem do diretório atual, você pode definir uma função.

l () {
  if [ $# -eq 0 ]; then
    ls -l
  else
    ls -ld "$@"
  fi
}

Em seguida, l cr* lista os arquivos cujo nome começa com cr , mesmo que sejam diretórios. E l cron.daily listas cron.daily em si, não seu conteúdo; você pode usar ls cron.daily ou l cron.daily/* para listar o conteúdo. Mas l lista os arquivos no diretório atual.

Com a função acima, l -a passará o sinal -d . Se você não quiser isso, você pode fazer as opções de descarte da função ao determinar se ele possui argumentos de nome de arquivo.

l () {
  local a
  a=("$@")
  while [[ $1 = -* ]]; do shift; done
  if [ $# -eq 0 ]; then
    ls -l "${a[@]}"
  else
    ls -ld "${a[@]}"
  fi
}

Se o que você deseja é um comando cmd , para que cmd cron.daily liste os arquivos no subdiretório cron.daily , mas cmd cd* listas cron.daily em si, isso é impossível no bash. No momento em que o comando é executado, o shell expandiu os curingas e o comando não pode saber se você usou curingas ou não.

Isso é possível em zsh , porque em zsh você pode desabilitar a expansão de curingas para um comando específico. Zsh não é o shell padrão na maioria dos sistemas, mas é apenas uma instalação de pacote de distância. Em zsh, você pode definir um alias com o noglob prefix :

alias l='noglob list_files_or_directory_contents'

Você precisará definir essa função list_files_or_directory_content - sua necessidade é incomum, então provavelmente ela ainda não existe. Aqui está uma função que eu acho que faz o que você está procurando: listar o conteúdo dos diretórios especificados diretamente e listar os próprios diretórios se eles vierem de uma expansão curinga.

list_files_or_directory_contents () {
  local arg matches
  setopt local_options no_csh_null_glob no_null_glob no_nomatch no_glob_subst no_sh_word_split
  if (($#==0)); then
    # No arguments: list the directory itself
    ls -l
  else
    for arg; do
      matches=($~arg)
      if [[ $#matches -eq 1 && $matches[1] == $arg ]]; then
        # Not a wildcard pattern: list the directory contents if it's a directory
        ls -l -- $arg
      else
        # Wildcard pattern: list the matches themselves, even the ones that are directories
        ls -ld -- $matches
      fi
    done
  fi
}
    
por 17.06.2016 / 01:45
0

Acho que isso vai fazer o que você quiser. A abordagem poderia, suponho, ser aplicada a tantas utilidades quantas quisesse. Mas eu realmente não recomendaria isso porque vai quebrar seus "hábitos dos dedos" quando você for para um novo sistema que ainda não tenha mexido.

ls() { [[ 0 == $# ]] && set -- *; /bin/ls -d "$@"; }

Por extensão, seu alias seria substituído por essa função:

lx() { [[ 0 == $# ]] && set -- *; /bin/ls -lartd "$@"; }
    
por 17.06.2016 / 14:26
-1

Aqui está uma função de shell que faz o que você quer. Você pode colá-lo diretamente no seu terminal ou adicioná-lo ao arquivo de inicialização do seu shell (por exemplo, ~/.bashrc for bash):

function dir {
  if [ -n "$1" ]
  then
     ls -lartd "$@"
  else
     ls -lartd *
  fi
} 
    
por 17.06.2016 / 14:24