내 디렉토리에는 약 100,000개의 파일이 있습니다. 상상할 수 있듯이 이것은 이상적인 상황이 아니며 디렉터리를 하위 디렉터리로 분할하고 싶습니다. 하지만 파일 이름 때문에 이름이나 기타 항목을 기준으로 하위 디렉터리에 넣을 수 없으므로 10개의 디렉터리를 만들고 각 디렉터리에 약 1000개의 파일을 넣으려고 합니다. 이를 수행할 수 있는 간단한 bash 명령이나 루프가 있습니까?
답변1
노력하다:
n=0; for f in *; do d="subdir$((n++ / 1000))"; mkdir -p "$d"; mv -- "$f" "$d/$f"; done
n
이동된 파일 수를 추적합니다. 수천 개의 배치로 각 파일은 이름이 지정된 하위 디렉터리에 할당됩니다 subdir$((n++ / 1000))
. (필요한 경우 이름 지정을 조정할 수 있습니다.) mkdir -p "$d"
아직 생성되지 않은 경우 이 하위 디렉터리를 생성합니다. mv -- "$f" "$d/$f"
파일을 이 하위 디렉터리로 전송합니다.
답변2
소스 디렉터리의 파일 수를 고려하면 제안된 해결 방법은 몇 분 정도 걸릴 수 있습니다.
기다리고 싶지 않다면 모든 이동에 대해 프로세스를 생성하지 않는 솔루션을 고려할 수 있습니다.
일괄 이동의 경우 이동과 유사 하다는 사실을 활용할 수 있습니다. cpio
즉 , 소스와 대상이 동일한 파일 시스템에 있으면 작업이 빨라지고, 그렇지 않으면 전체 복사본이 생성됩니다.--pass-through
--link
달리 mv
: 각 소스 파일에 대한 하드 링크가 남지만 작업이 성공하면 cpio -lpd
나중에 모두 쉽게 삭제할 수 있습니다.rm -r
디렉터리 분할기의 구현은 다음과 같습니다.
split_dir()(
local src=$1 nbatches=$2 dest=$3
local tmpd=
trap 'rm -rf "$tmpd"' EXIT
tmpd="$(mktemp -d "$tmpd")"
find -type f "$src" > "$tmpd/files"
local nfiles=$(wc -l < "$tmpd/files")
local batchsz=$((nfiles/nbatches))
( cd "$tmpd"; split -l "$batchsz" -d files )
local i
for((i=0;i<nbatches;i++)); do
mkdir -p "$dest/$i"
< x$i cpio -pdl "$dest/$i"
done
)