web-dev-qa-db-ja.com

ターゲットフォルダが空の場合にのみ、ファイルを1つずつディレクトリに自動的に移動します

出来ますか?そしてのアルファベット順?

基本的に、これは次のとおりです。 ディレクトリとそのサブディレクトリから別のディレクトリにファイルをタイプ別に再帰的に移動するにはどうすればよいですか?

各ファイルが宛先ディレクトリに移動されないことを除いてでない限り、別のプロセスがその宛先ディレクトリ内の唯一のファイルをフェッチし、それを別の場所に移動しました(したがってターゲットフォルダは空で、次のファイルをそこに移動する準備ができています)。

3
iceequal

このようなものが欲しいですか?

#!/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

このスクリプトは、すべてのファイルがコピーされるまで実行されます。ターゲットが空の場合にのみファイルを$targetにコピーするため、別のプロセスがファイルの受信時にファイルを削除しない限り、ファイルは永久にハングします。

ファイルまたは$targetの名前に新しい行(\n)が含まれていると壊れますが、スペースやその他の奇妙な文字で問題ないはずです。

2
terdon

_inotify-wait_ from _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
)
_

説明:

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

    内部フィールドセパレータ_$IFS_が改行文字に設定されているサブシェルでスクリプトの本体を実行し、forループがスペースを含むファイル名を適切に処理できるようにします。 _$'string'_構文により、bashstringのエスケープシーケンスを解釈するため、_$'\n'_は改行文字として正しく解釈されます。

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

    _$SOURCE_とそのサブディレクトリ内のファイルの逆ソートリストを作成し、リストを一度に1ファイルずつ繰り返し、_$FILE_の値を次に移動するファイルに設定します。

  • _mv "$FILE" "$DEST"_

    現在の_$FILE_を_$DEST_ディレクトリに移動します。

  • _inotifywait -e moved_from "$DEST"_

    inotify 監視を確立します。これは、ファイルが監視対象ディレクトリから移動されたときにトリガーされます。これにより、_$DEST_ディレクトリが空になっている間、スクリプトがブロックされます。スクリプトが呼び出されると、_$DEST_は空であると見なされます。

2
Thomas Nyman