Usando sed para substituir todas as ocorrências no início por um número correspondente de cadeias de substituição

1

Eu estou olhando para manipular a saída de $ tree --noreport $ de tal forma que substitui os caracteres de desenho de caixa e os espaços principais em cada linha com um número correspondente de espaços. Se eu fosse escrever o padrão para combinar esses caracteres, seria ^\(\u2500\|\u2514\|\u251C\| \)*\u2500 . Esta cadeia seria agrupada em $'...' porque as sequências de escape Unicode não são reconhecidas pelo sed. Esse padrão ocorre em todas as linhas da saída de tree --noreport , exceto na primeira. Cada caractere em cada string correspondente precisa ser substituído por um espaço.

Exemplo de entrada:

.
├── docs
│   ├── jokes
│   │   └── knock_knock.txt
│   └── work
├── images
└── .profile

Exemplo de saída:

.
    docs
        jokes
            knock_knock.txt
        work
    images
    .profile

Agora estou percebendo que preciso remover a ambigüidade sobre onde o nome de um arquivo ou pasta é iniciado (o nome de um arquivo ou pasta pode começar com um ou mais espaços), então a saída deve ficar parecida com:

.
    /docs
        /jokes/
            /knock_knock.txt
        /work
    /images
    /.profile

O \u2500 no final do meu padrão fornecido realmente distingue entre a formatação da árvore e o início do nome do arquivo / pasta.

    
por Melab 26.03.2018 / 04:57

2 respostas

1

Você pode substituir um por vez em um loop como:

tree --noreport | sed $'
  :1
    s/^\( *\)\([\ua0\u2500\u2502\u2514\u251C]\)\([\ua0\u2500\u2502\u2514\u251C ]*\u2500 \)/\1 \3/
  t1
  s|\u2500 |  /|'

(você perdeu \ua0 (espaço sem quebra) e \u2502 ( também mostrado na sua amostra) pelo menos, que aparecem na saída da minha versão de tree , pelo menos).

Isso é enganoso se houver arquivos cujo nome contenha "─ " , opcionalmente precedido por alguns desses caracteres.

Outra abordagem (supondo que você queira inserir o / e que os diretórios que você está chamando tree on não contêm "─ " ): insira um / após a primeira ocorrência de "\u2500 " e, em seguida, substitua todos os caracteres antes do primeiro / por um espaço em um loop.

tree --noreport | sed '
  s|'$'\u2500'' |&/|;t1
  b
  :1
    s|^\( *\)[^ /]| |
  t1'

É um pouco mais fácil com perl :

tree --noreport | perl -C -pe 's{^.*?\x{2500} }{" " x length($&) . "/"}e'
    
por 26.03.2018 / 08:05
1

Esta é uma função bash que produz os nomes encontrados em um diretório superior recursivamente:

mytree () (
    topdir="${1-.}"
    indent="${2-0}"

    shopt -s nullglob
    shopt -s dotglob

    # output directory name
    printf "%${indent}s'%s'/\n" "" "${topdir##*/}"

    indent=$(( indent + 4 ))

    for name in "$topdir"/*; do
        if [ -h "$name" ]; then
            # output symbolic link name and target
            printf "%${indent}s'%s' --> '%s'\n" "" "${name##*/}" "$( readlink -- "$name" )"
        elif [ -d "$name" ]; then
            # recurse into directories
            mytree "$name" "$indent"
        else
            # output other type of name (not directory or symbolic link)
            printf "%${indent}s'%s'\n" "" "${name##*/}"
        fi
    done
)

A função mytree recebe um argumento (o segundo argumento é usado apenas em chamadas recursivas), que é o diretório principal a ser processado. Se nenhum argumento for fornecido, ele usará o diretório atual como o diretório principal a ser listado.

A saída é como a seguinte:

'Work'/
    'Data'/
        's3wes.all.tab.frq.counts'
        's3wes.con.tab.frq.counts'
        'sullivan.txt'
    'Development'/
        'ENA-submission'/
            '.git'/
                'COMMIT_EDITMSG'

etc.

Ou seja, os nomes são citados com aspas simples e os diretórios terão um / à direita. Além disso, os links simbólicos serão mostrados como, por exemplo,

'embl-validator.jar' --> 'embl-api-validator-1.1.158.jar'

O formato de saída pode ser facilmente alterado alterando as três printf chamadas.

    
por 26.03.2018 / 12:49