Mover automaticamente os arquivos para um diretório, um por um, e somente quando a pasta de destino estiver vazia

3

É possível? E em inverter ordem alfabética?

Essencialmente, isso: Como posso mover arquivos por tipo recursivamente de um diretório e seus subdiretórios para outro diretório?

Exceto que cada arquivo não é movido para o diretório de destino a menos que um processo separado tenha buscado o único arquivo no diretório de destino e movido para outro lugar (assim a pasta de destino está vazia e 'pronta' para o próximo arquivo a ser movido para lá).

    
por iceequal 09.09.2013 / 06:08

2 respostas

2

Você quer algo assim?

#!/usr/bin/env bash
## This is the target path, the directory
## you want to copy to.
target="some/path with/spaces";

## Find all files and folders in the current directory, sort
## them reverse alphabetically and iterate through them
find . -maxdepth 1 -type f | sort -r | while IFS= read -r file; do
    ## Set the counter back to 0 for each file
    counter=0;
    ## The counter will be 0 until the file is moved
    while [ $counter -eq 0 ]; do
      ## If the directory has no files
      if find "$target" -maxdepth 0 -empty | read; 
      then 
          ## Move the current file to $target and increment
          ## the counter.
          mv -v "$file" "$target" && counter=1; 
      else
          ## Uncomment the line below for debugging 
          # echo "Directory not empty: $(find "$target" -mindepth 1)"

          ## Wait for one second. This avoids spamming 
          ## the system with multiple requests.
          sleep 1; 
      fi;
    done;
done

Este script será executado até que todos os arquivos tenham sido copiados. Ele só copiará um arquivo para $target se o destino estiver vazio, então ele irá travar para sempre, a menos que outro processo esteja removendo os arquivos assim que eles chegarem.

Ele será quebrado se os nomes dos arquivos 'ou $target contiverem novas linhas ( \n ), mas devem ficar bem com espaços e outros caracteres estranhos.

    
por 09.09.2013 / 07:23
2

Solução simples usando inotify-wait de inotify-tools :

#!/bin/bash
SOURCE=$1
DEST=$2
(
IFS=$'\n'
for FILE in $(find "$SOURCE" -type f | sort -r); do
  mv "$FILE" "$DEST"
  inotifywait -e moved_from "$DEST"
done
)

Explicação:

  • (IFS=$'\n' ...)

    Executa o corpo do script em um subshell no qual o separador de campo interno $IFS é definido como um caractere de nova linha, permitindo que o loop for manipule nomes de arquivos com espaços corretamente. A sintaxe $'string' faz com que bash interprete sequências de escape em string , portanto, $'\n' é interpretado corretamente como o caractere de nova linha.

  • for FILE in $(find $SOURCE -type f | sort -r)

    Cria uma lista classificada reversa de arquivos em $SOURCE e seus subdiretórios e repete por meio da lista um arquivo por vez, definindo o valor de $FILE para o próximo arquivo a ser movido.

  • mv "$FILE" "$DEST"

    Move o diretório atual $FILE para $DEST .

  • inotifywait -e moved_from "$DEST"

    Estabelece uma inotify que é acionada quando um arquivo é saiu do diretório assistido. Isso fará com que o script bloqueie enquanto o diretório $DEST é esvaziado. Assume-se que $DEST está vazio quando o script é invocado.

por 09.09.2013 / 08:42