Por isso, muitíssimo impaciente, usei o seguinte script no meu servidor 19.04, na tentativa de mover vários arquivos de vídeo para pastas com prefixos:
dirs=(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)
shopt -s nocasematch
for file in *
do
for dir in "${dirs[@]}"
do
if [ -d "$file" ]; then
echo 'this is a dir, skipping'
break
else
if [[ $file =~ ^[$dir] ]]; then
echo "----> $file moves into -> $dir <----"
mv "$file" "$dir"
break
fi
fi
done
done
Nenhuma pista de onde deu errado, mas, em vez de mover os arquivos para as pastas, foi para uma saída singular .. então:
----> a1.ts moves into -> A <----
----> a2.ts moves into -> A <----
----> a3.ts moves into -> A <----
----> a4.ts moves into -> A <----
----> a5.ts moves into -> A <----
----> c1.ts moves into -> C <----
----> c2.ts moves into -> C <----
----> c3.ts moves into -> C <----
----> c4.ts moves into -> C <----
----> c5.ts moves into -> C <----
Felizmente, parei o processo (CTRL + C) assim que percebi que não estava indo como o esperado e não passei por toda a pasta.
Então agora eu tenho esses arquivos A
e C
, que são menores que um Gb, e pela aparência dele é um vídeo ÚNICO.
Existem 50 GB não contabilizados no uso total do disco da própria pasta, mas o espaço total em disco do computador permaneceu o mesmo. Me fazendo pensar que os arquivos não foram excluídos?
Qualquer ajuda apreciada, obrigado :)
Editar: os arquivos acabaram, apenas o último arquivo a ser gravado permanece, bastou algum tempo para que as informações de uso do disco fossem atualizadas .. moral da história, execute seus scripts em arquivos simulados antes!
fonte
A
,B
e assim por diante existia antes de executar o script? Caso contrário, você apenas renomeou os arquivos. Todos os arquivos cujos nomes começarama
ouA
foram renomeadosA
, portanto, apenas o último arquivo renomeado sobreviveu, os outros são substituídos. Chamar uma variáveldir
não cria um diretório!mv "$file" "$dir/"
, com um final/
; se$dir
não existir,mv
ocorrerá um erro em vez de renomear$file
para$dir
. Considere tambémmv -i
emv -n
. E sempre faça ummkdir -p
antes de mover, para uma boa medida.Respostas:
Eu acho que esse é o problema: você deveria ter criado os diretórios A, B, C ... Z. Se criou, o
mv
comando deveria ter movido os arquivos para esses diretórios.Mas se não, o
mv
comando move os arquivos para arquivos com esses nomes, A, B, C ... e acho que foi isso que você fez.Para tornar o shellscript mais seguro, você deve criar os diretórios (se eles ainda não estiverem lá) antes de iniciar a mudança.
Se quiser que as coisas fiquem ainda mais seguras, você também pode usar
mv
com a-i
opçãofonte
touch
seria um bom substituto paramkdir
evitar conflitos no caso de executar o script várias vezes?touch
cria um arquivo se o nome não existir. Portanto, não fará o que você deseja neste caso.mkdir -p
pode lidar com o uso do script várias vezes.mv
mais seguro é fazer com que o hábito de adicionar uma barra final para o nome de destino quando o alvo é um diretório ou sejamv "$file" "$dir/"
O @Sudodus já explicou o que deu errado, mas aqui está uma versão mais simples do seu script da próxima vez:
Explicação
for letter in {a..z}; do
:{a..z}
expande para todas as letras minúsculas entrea
ez
:Portanto, isso irá iterar todas as letras minúsculas, salvando cada uma como
$letter
.dir=${letter^}
: a sintaxe${var^^}
retorna o conteúdo da variável$var
com o primeiro caractere em maiúsculas (já que este possui apenas um caractere, é tudo o que precisamos). Então, se$letter
éa
, então${letter^^}
éA
e, portanto$dir
, será a versão em maiúscula da corrente$letter
.mkdir -p -- "$dir"
: crie o diretório Se já existir, não faça nada (-p
). A--
significa o fim das opções , e é útil para proteger contra os nomes que começam com-
.mv -- "$letter"* "${letter^}"* "$dir"
: mova todos os arquivos (ou diretórios) para o destino relevante.O problema é que ele também moverá os diretórios que você tiver. Ele não moverá os diretórios de destino, porque eles ainda não existem ou você tentará movê-los para eles mesmos, mas quaisquer diretórios existentes que não sejam o diretório de destino serão movidos.
Se isso for um problema, você terá que fazer algo assim:
fonte
${letter^}
e${letter^^}
, e se eles são idênticos, por que usar${letter^^}
no lugar de$dir
?${var^}
maiúscula apenas a primeira letra, enquanto${var^^}
todas as letras em maiúscula. Não faz nenhuma diferença aqui, pois$letter
só tem uma letra.$dir
no diretóriomv
. (Na sua forma actual ele irá falhar se um preexiste arquivo com um nome maiúscula de uma única letra)Em vez de verificar todos os arquivos em uma matriz de dicionário que cria muita iteração, você pode comparar arquivos com padrões.
Tipo muito básico:
fonte
Proteja seu .bashrc:
fonte
-n Do not overwrite an existing file. (The -n option overrides any previous -f or -i options.)
isso, importa que a tag -n seja antes de seguir as tags? O --backup = numerado criará o dobro de cada direito, não é um exagero (e energia / consumo de espaço) ao lidar com arquivos de vídeo super grandes (terabytes em conversação). Obrigado !Para o registro, algumas maneiras de impedir a
mv
substituição de arquivos existentes:Se você deseja mover para um diretório, adicione uma barra ao destino, ou seja, use em
mv "$file" "$dir"/
vez demv "$file" "$dir"
. Se$dir
não existir ou não for um diretório, vocêmv
irá reclamar:Isso parece fazer a chamada do sistema
rename("a", "z/")
, portanto, ela deve estar protegida das vulnerabilidades do tempo de verificação ao tempo de uso, caso alguém esteja manipulando o mesmo conjunto de arquivos ao mesmo tempo.Como alternativa, use
mv -t "$dir" "$file"
. Novamente, ele reclamará se$dir
não for um diretório.Use a
-n
opção para evitar a substituição de arquivos existentes:Não impedirá que renomeie o primeiro arquivo, mas depois não o descartará com os outros.
Isso parece ser simples
rename()
, portanto pode não ser seguro com o manuseio simultâneo. (Existerenameat2()
um suporte para um sinalizador para evitar a substituição.)fonte
Embora aparentemente não seja o seu caso, é possível que você possa fazer isso e não perder os arquivos. Isso exigiria que uma das duas coisas fosse verdadeira:
Os sistemas de arquivos Unix permitem que mais de uma entrada de diretório se refira exatamente ao mesmo conteúdo de arquivo . Isso é chamado de ' link físico '. Você pode criar links físicos com o
ln
comando, sem a opção comum-s
(suave / simbólica). Enquanto existir pelo menos um link físico para o conteúdo do arquivo, ele não será reutilizado pelo sistema de arquivos.(Observação: as permissões geralmente se aplicam ao conteúdo do arquivo, não à entrada do diretório. É por isso que um usuário comum às vezes pode excluir um arquivo pertencente a
root
, mas não gravar nele. A operação de exclusão modifica a pasta, não o próprio arquivo. )O sistema de arquivos também não reutilizará o conteúdo do arquivo, desde que pelo menos um processo tenha o arquivo aberto. Mesmo que não exista uma entrada no diretório, o sistema de arquivos não considerará o espaço livre até que nenhum processo o abra. O arquivo pode ser recuperado do sistema
/proc/<pid>/fd
de arquivos virtualroot
enquanto o arquivo permanecer aberto. (Obrigado @fluffysheap.)fonte