Para um conjunto relativamente pequeno de pastas, você pode usar um loop numérico
for n in {1..272}
do
d="conf$n"
test-d "$d" && cat "$d/distance.txt" >> /path/to/folder/d.txt
done
Eu tenho um monte de pastas que são rotuladas desta forma:
conf1
conf2
...
Mas a ordem no diretório inicial é como
conf1
conf10
conf100
conf101
...
conf2
conf20
conf200
conf201
...
Como cada pasta contém um arquivo chamado "distance.txt", eu gostaria de poder imprimir o conteúdo do arquivo distance.txt, de cada pasta, mas na ordem, indo da pasta 1 - > 2 - > 3 ... para a pasta final 272.
Eu tentei várias tentativas, mas toda vez que o arquivo final contém todo o conjunto de valores na ordem errada; essa é a parte do código que eu configurei:
ls -v | for d in ./*/;
do (cd "$d" && cat distance.txt >> /path/to/folder/d.txt
);
done
Como você pode ver, tentei "ordenar" as pastas com o comando
ls -v
e, em seguida, acoplar o ciclo para salvar iterativamente cada arquivo.
Você pode gentilmente me ajudar?
Se você tem um sort
que suporta delimitadores nulos e classificação de versões, você pode fazer com segurança
printf '%sfor d in conf*(/n); do
whatever with "$d"
done
' conf*/ | sort -zV | while read -rd '' d; do
whatever with "$d"
done
eu acho. Se você tem zsh
é muito mais fácil, pois suporta um qualificador de glob numérico
printf '%sfor d in conf*(/n); do
whatever with "$d"
done
' conf*/ | sort -zV | while read -rd '' d; do
whatever with "$d"
done
printf '%s\n' conf{1..101} conf{2..272} |
xargs sh -c 'shift "$1"; printf "%s/distance.txt\n" "$@"' 2 1 > /path/to/folder.txt
Ou
printf '%s\n' conf{1..101}/distance.txt conf{2..272}/distance.txt |
xargs cat > /path/to/folder.txt
printf 'conf%s/distance.txt\n' {1..272} | xargs cat >/path/to/folder/d.txt 2>/dev/null
Aqui fazemos uso do fato de que se o dir. confNNN/
& / ou distance.txt não existem, será gerado um aviso que ignoramos. A saída real acontece apenas no caso do arquivo dir + existir, portanto, não há necessidade de testar o arquivo & dir. existência. cat
para o resgate.
Além disso, não há necessidade de >>
de acréscimo, como xargs
, mesmo que invoque cat
várias vezes, e ainda despeja a saída em um grupo no log.
Então, é um lugar que não é um UUOC
; -)
Crie um minúsculo perlscript para ordenar os argumentos passados pelo shell:
#!/usr/bin/perl -l -s
$re ||= qr/(\d+)/;
sub bynum {
($aa) = $a =~ $re;
($bb) = $b =~ $re;
return $aa <=> $bb;
}
map { print } sort bynum @ARGV;
Salve o script como sortargsbynum
e chame-o como expressão de shell:
for d in $(sortargsbynum conf*); do
cat $d/distance.txt >> /path/to/folder/d.txt
done
Você pode transmitir uma expressão regular especial para correspondência, por exemplo, para corresponder apenas a um número no final do nome:
for d in $(sortargsbynum -re='(\d+)$' *conf*); do
echo $d
done
conf1
conf2
conf10
conf20
conf99
1stconf100
2ndconf100
conf101
conf200
conf201
Você pode classificar primeiro pelo comprimento da string e depois lexicograficamente se tudo compartilhar um prefixo comum. Se dois números tiverem o mesmo número de dígitos, a comparação lexicográfica e numérica resultará na mesma ordem.
ls -1 | awk '{print $1 " " length($1)}' | sort -n -k2,2 -k1,1 | awk '{print $1}'
Você também pode usar perl para coletar os nomes das pastas e extrair o sufixo numérico à direita. Então você pode ordenar numericamente com base neste sufixo.
ls -1 | perl -e '@lines = <STDIN>; @lines = sort { $a =~ /(\d+)$/; $aa = $1; $b =~ /(\d+)$/; $aa <=> $1; } @lines; print foreach @lines;'