'$ RANDOM' não é aleatório dentro de 'find''s' -exec '

3

Estou tentando encontrar e mover um monte de pastas em uma caixa linux.

Todas as pastas têm o mesmo nome, por isso estou usando echo $RANDOM para fornecer um número aleatório para usar em um nome de pasta.

echo $RANDOM
realmente produz um número aleatório toda vez que é executado. No entanto, find . -type d -name .AppleDouble -exec mv \'{}\' \'/raid/data/Storage/AppleDouble/'echo $RANDOM' \;
usa o mesmo número "aleatório" para cada pasta e, como resultado, move apenas uma pasta.

Acho que o problema é que $RANDOM está sendo avaliado imediatamente quando find começa a ser executado. Como posso escapar para que o valor de $RANDOM não seja avaliado até que a opção -exec comece a ser executada (ou qual é a melhor maneira de fazer isso)?

Observação: estou no busybox, por isso não consigo instalar nada.

    
por Fake Name 27.04.2012 / 09:13

3 respostas

0

Não tenho muita certeza de qual foi o problema.

Eu acabei desistindo e escrevi um script externo para passar para find ' -exec ' e isso parece estar funcionando.

Não sei por que não coloquei o comando inteiro em uma linha. Parece que há alguns bugs estranhos na versão do busybox e do bash que eu tenho (esta é uma versão antiga de ambos. É o busybox 1.1.0, que é de 2006, e o bash 3.00.16 que é de uma idade semelhante (não consigo encontrar um histórico de lançamento de bash)).

    
por 05.05.2012 / 09:28
5

Você está correto; você não citou, então é avaliado pelo shell ao construir a linha de comando find . -exec não usa bash normalmente, por isso, se você citar ou escapar do $ , ele não será expandido.

A solução é invocar bash dentro de -exec :

find . -type d -name .AppleDouble -exec bash -c 'echo $RANDOM' \;
    
por 27.04.2012 / 09:16
1

Existem vários problemas com o comando que você está executando.

mv \'{}\' \'/raid/data/Storage/AppleDouble/'echo $RANDOM'

'echo something' é equivalente a something (exceto quando something contém alguns caracteres especiais, em cujo caso o efeito da echo adicional e a substituição de comando geralmente pioram as coisas). Então, essa é uma maneira complicada de escrever

mv \'{}\' \'/raid/data/Storage/AppleDouble/$RANDOM

Portanto, o shell passa três parâmetros para o comando find da parte da linha de comando representada acima: mv , '{}' e '/raid/data/Storage/AppleDouble/12345 , em que 12345 é um valor aleatório. Como o valor da variável especial RANDOM é expandido pelo shell antes de invocar find , todos os comandos executados por find serão executados com o mesmo valor. Note também que você tem aspas simples que serão partes dos nomes dos arquivos - apenas solte-as.

Como você deseja expandir $RANDOM em cada chamada, é necessário informar find para executar um shell que executará mv , em vez de ter find execute mv diretamente.

find . -type d -name .AppleDouble -exec sh -c 'mv "$0" /raid/data/Storage/AppleDouble/$RANDOM' {} \;

Observe que a probabilidade de uma colisão nos números aleatórios é bastante alta: $RANDOM só aumenta para 2 15 , portanto, se você estiver copiando mais de 213 arquivos, a probabilidade de dois arquivos serem copiados para o mesmo destino é maior que 50%. É uma péssima ideia usar um nome aleatório neste contexto. Em vez disso, use um nome que seja garantido como distinto para cada arquivo de origem. Uma maneira de fazer isso é usar um hash criptográfico do caminho de origem:

find . -type d -name .AppleDouble -exec sh -c 'mv "$0" /raid/data/Storage/AppleDouble/$(echo "$0" | md5sum | cut -d " " -f 1)' {} \;
    
por 30.04.2012 / 03:23

Tags