80GB 파일이 포함된 폴더에서 30GB 파일을 이동하는 방법은 무엇입니까?

80GB 파일이 포함된 폴더에서 30GB 파일을 이동하는 방법은 무엇입니까?

500개 이상의 비디오가 포함된 폴더가 있는데 폴더 크기는 약 80GB입니다.

30GB의 비디오를 다른 폴더로 이동하고 싶은데 어떻게 해야 합니까?

터미널을 사용하고 있는데 GUI를 설치할 수 없습니다.

답변1

비선택적으로(자동으로)

이 작업을 수행할 수 있는 단일 명령줄 도구는 모르겠습니다. 하지만 스크립트를 사용하여 특정 전체 크기가 이동할 때까지 파일을 이동할 수 있습니다. 예를 들어 다음과 같습니다(스크립트를 한 번만 실행하세요. 다시 실행하면 남은 파일에서 지정된 크기만큼 다시 이동됩니다.):

#!/bin/bash

sourc_dir="/path/to/directory" # Set the path to the source directory "no trailing /"
dest_dir="/path/to/directory" # Set the path to the destination directory "no trailing /"
move_size="30" # Set the total size of files to move in Gigabytes
 
# Don't edit below this line
move_size=$(( move_size * 1000000 ))
current_size=$(du -sk "$sourc_dir" | awk '{printf "%d", $1}')
remaining_size=$(( current_size - move_size ))

for f in "$sourc_dir"/*; do
  [ -f "$f" ] || continue
  new_size=$(du -sk "$sourc_dir" | awk '{printf "%d", $1}')
  (( new_size <= remaining_size )) && exit
  mv -n -- "$f" "$dest_dir"/
  done

아니면 한 줄짜리(스크립트 파일이 필요하지 않습니다) 터미널에서 다음과 같이 실행할 수 있습니다.

for f in /path/to/source/*; do [ -f "$f" ] || continue; (( size >= (30*(1000**3)) )) && break || (( size += $(stat --printf "%s" "$f") ))  && mv -n -- "$f" /path/to/destination/; done

unset size동일한 셸 인스턴스에서 다시 실행하고 싶을 수도 있습니다 .

선택적으로(수동으로)

파일 이름, 크기, 유형 등을 기반으로 검색 도구에서 언제든지 쉘 패턴이나 파이프를 지정할 수 있습니다.

또는 더 편리하게는 잘 알려져 있고 기능이 풍부한 파일과 같은 여러 파일 선택을 지원하는 콘솔 기반 파일 관리자를 사용할 수 있습니다.GNU 자정 사령관Ubuntu 공식 리포지토리에서 사용할 수 있으며 다음과 같이 설치할 수 있습니다.

sudo apt install mc

mc입력 하고 실행하려면 Enter... 키보드 키를 사용하여 여러 파일을 선택할 수 있는 탐색 가능한 UI가 표시됩니다 Insert... 선택한 파일의 전체 크기와 개수를 볼 수 있습니다 실시간으로 다음과 같이:

여기에 이미지 설명을 입력하세요

이동하려는 파일을 모두 선택했으면 F6키보드 키를 눌러 이동/이름 바꾸기 대화 상자를 열고 대상 디렉터리를 입력한 후 [< OK >]다음과 같이 선택한 파일을 한 번에 이동하도록 선택합니다.

여기에 이미지 설명을 입력하세요

또는 기능이 적고 덜 알려진 것일 수도 있습니다.ff (빌어먹을 빠른 파일 관리자):-) ... 흥미롭게도 bash... 여러 파일 선택을 지원하지만 선택한 전체 파일 크기를 보려면 약간 사용자 정의해야 할 수도 있습니다. 예를 들어 빠른 패치로 줄을 변경할 수 있습니다 159. 소스 fff파일은 다음과 같습니다.

local mark_ui="[${#marked_files[@]}] selected (${file_program[*]}) [p] ->"

이에:

local mark_ui="[${#marked_files[@]}] $(for f in "${marked_files[@]}"; do (( tsize += $(stat --printf "%s" "$f") )); done; tsize=$((tsize/(1000**2))); printf '[%d M]' "$tsize";) selected (${file_program[*]}) [p] ->"

그런 다음 해당 파일을 다음과 같이 간단히 실행할 수 있습니다(설치가 필요하지 않습니다):

bash fff

또는 다음과 같이 사용법에 대한 도움말을 확인하세요.

bash fff -h

그런 다음 해야 할 일은 소스 디렉터리로 이동하여 m(소문자) 키보드 키는 다음과 같습니다:

여기에 이미지 설명을 입력하세요

p파일 선택이 완료되면 대상 디렉터리로 이동하고 ( 를 눌러 이전에 선택한 파일을 해당 디렉터리로 이동합니다.소문자) 키보드 키.

답변2

여기에 대한 대안이 있습니다라파du모든 파일에 대해 전체 디렉토리 를 요구하지 않는 아이디어입니다 . 대신 stat각 파일에 대해 수행합니다.한 번, find's를 사용하여 -printf %s크기를 가져오고 %p이동할 파일의 경로를 가져옵니다.

#!/bin/bash

src='foo'
dest='bar'

# 30GB in bytes to move:
(( bytestomove=30*(1000**3) ))
movedbytes=0

while IFS=$'\t' read -r -d '' bytes file
do
    # if we already moved enough, break out
    (( movedbytes >= bytestomove )) && break;

    # try to move it, break out if it fails
    mv -n -- "$file" "$dest" || break

    # successfully moved, add bytes to movedbytes
    (( movedbytes += bytes ))
done < <(find "$src" -type f -printf "%s\t%p\0")

(( movedmegs=movedbytes/(1000**2) ))
printf "Moved %d MB\n" $movedmegs

답변3

@TedLyngmo는 제가 처음 제시한 tar 솔루션이 파일을 효과적으로 복사하고 이동하지 않는다는 점을 지적했습니다. 이러한 구별은 다음 두 가지 이유로 중요합니다.

  1. 복사본을 사용하면 소스 파일이 그대로 유지되지만 이동을 사용하면 소스 파일이 더 이상 소스 위치에 존재하지 않습니다.
  2. 파일이 동일한 파일 시스템 내에서 이동된 경우 이 질문의 경우와 마찬가지로 mv소스 파일을 새 위치에 다시 연결하고 내용을 전혀 복사하지 않습니다. 이는 일반적으로 특히 대용량 파일의 경우 복사보다 훨씬 빠릅니다.

시나리오 이동

tar원래 제공된 복사 시나리오의 개념을 계속 사용하여 tar찾은 파일의 처음 30GB만 포함하는 파일 목록을 작성한 다음 해당 파일만 이동할 수 있습니다.

#!/bin/bash

# Convert human-readable number, e.g. 1M, 30G to number of 1024 byte blocks 
limit=$(numfmt --from=auto $1 --to-unit 1024)
src_dir=$2
dest_dir=$3

mkdir $dest_dir
filelist=$(readlink -f $(mktemp -p $dest_dir))

# create a list of files to be moved.  tar -v outputs filenames to stdout, and 
# the dest archive is /dev/null
tar -v -L $limit -F false -c -f /dev/null -C $src_dir . > $filelist 2> /dev/null
tar_result=$?
if [ "$tar_result" = 2 ]; then
    echo "$1 limit was hit - some unmoved files will remain in $dest_dir"
else
    echo "All files will be moved"
fi

pushd $dest_dir > /dev/null
abs_dest_dir=$PWD
# create directories in the destination
grep '/.*/$' $filelist | xargs mkdir -p
popd > /dev/null

pushd $src_dir > /dev/null
# create hard links in the destination
grep -v '/$' $filelist | xargs cp -l --parents -t $abs_dest_dir
# unlink source files
grep -v '/$' $filelist | xargs rm
# remove source directories in reverse order, if they are empty
grep '/.*/$' $filelist | tac | xargs rmdir --ignore-fail-on-non-empty
popd > /dev/null

rm $filelist

이것은 내가 원하는 것보다 더 복잡합니다.

  • mv여러 파일에 대한 소스 및 대상 경로를 그다지 제어하지 않으므로(특히 cp' --parents 옵션과 유사하지 않음) 대상 위치에 하드 링크를 만든 다음 소스 파일 링크를 해제하여 파일 이동이 이루어집니다.

  • 소스 디렉터리에는 이동할 항목과 이동할 수 없는 항목이 혼합되어 있으므로 디렉터리를 대상에서 다시 생성해야 하며 단순히 모든 내용과 함께 이동해서는 안 됩니다. 따라서 파일을 이동하기 전에 적절한 대상 디렉터리가 생성되고, 해당 소스 디렉터리가 비어 있으면 파일을 이동한 후 제거됩니다.

주의사항

  • tar -v한 줄에 하나의 파일 항목을 출력합니다. 경로 이름에 개행 문자와 같은 특수 문자가 있으면 이는 크게 실패합니다. 소스 경로 이름이 현명하게 지정되기를 바랍니다.

  • 스트림에는 실제 콘텐츠뿐만 아니라 메타데이터(파일 이름, 타임스탬프 등)가 포함되어 있으므로 실제 파일 데이터의 30GB보다 약간 적게 이동하며 이는 모두 30GB 제한이 적용됩니다.

  • 나는 여기서 KB 대 kb를 사용하여 약간 빠르고 느슨하게 플레이하고 있습니다. 매개 -L변수는 1024바이트 단위로 작동하므로 실제로는 tar 스트림의 3,072,000,000바이트로 이동이 제한됩니다. 숫자를 적절하게 조정하세요.

  • filelist.txt가 현재 디렉터리에 생성됩니다. 이를 위해서는 쓰기 권한이 필요합니다. 이동 작업에는 어쨌든 쓰기 권한이 필요하기 때문에 이것은 아마도 주어진 것입니다.

시나리오 복사

tar를 사용 하여 폴더를 스트림으로 전환한 다음 tar다시 스트림을 새 위치의 파일로 전환할 수 있습니다 . 첫 번째는 새 테이프를 요청하기 전에 "테이프 길이"를 3000000KB로 제한하는 데 tar사용됩니다 . -F를 사용하여 각 "테이프" 다음에 실행합니다 . 오류를 반환 하므로 첫 번째 "테이프"(예: 30GB) 이후 전송이 중지됩니다. 모든 데이터가 tar를 2번만 호출하는 것이 bash 루프를 사용하여 모든 파일을 반복하는 것보다 빠릅니다.-Ltarfalsefalse

mkdir dest.dir
tar -cv -L 3000000 -F false -C src.dir . | tar -x -C dest.dir/

그러면 30GB 제한에 도달할 때까지 파일이 복사되고, 그 다음에 tar는 다음과 같은 오류가 발생합니다.

tar: Unexpected EOF in archive
tar: Unexpected EOF in archive
tar: Error is not recoverable: exiting now
tar: ‘false’ command failed
tar: Error is not recoverable: exiting now

tar제한에 도달했을 때 전송 중이던 파일은 전송되지 않습니다. 대상에 전혀 기록되지 않습니다.

주의사항

  • 스트림에는 실제 콘텐츠뿐만 아니라 메타데이터(파일 이름, 타임스탬프 등)가 포함되어 있으므로 30GB 미만의 실제 파일 데이터가 복사되며 이는 모두 30GB 제한이 적용됩니다.

  • 나는 여기서 KB 대 kb를 사용하여 약간 빠르고 느슨하게 플레이하고 있습니다. 매개 -L변수는 1024바이트 단위로 작동하므로 실제로는 tar 스트림의 3,072,000,000바이트로 전송이 제한됩니다. 숫자를 적절하게 조정하세요.


이 답변의 이전 편집에서는 find-cpio-head-cpio를 사용한 다음 tar-head-tar를 사용했습니다. 지금 제시된 타르타르 솔루션은 충분하지만 다른 솔루션에 관심이 있는 경우 편집 기록을 검사하십시오.

답변4

파일이 있는 폴더로 이동합니다.

cd SOURCE_FOLDER

해당 폴더에 파일 목록 만들기

ls > list.txt

아무 편집기에서나 편집하고 이동하고 싶지 않은 파일을 제거하세요. 결과를 저장하면 이제 list.txt에 이동하려는 파일만 포함됩니다. 이제 list.txt 파일의 각 줄을 읽고 해당 파일을 대상 디렉터리로 이동하는 간단한 스크립트를 실행하세요.

while IFS= read -r line; do mv "$line" ../DESTINATION_DIRECTORY/"$line"; done < list.txt

관련 정보