그래서 바보 인내심은 19.04 서버에서 다음 스크립트를 사용하여 많은 비디오 파일을 접두사가있는 폴더로 옮기려고했습니다.
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
잘못되었다는 단서가 없지만 파일을 폴더로 옮기는 대신 단일 출력으로갔습니다.
----> 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 <----
의도 한대로 진행되지 않고 전체 폴더를 거치지 않는 즉시 프로세스 (CTRL + C)를 중지했습니다.
그래서 지금 나는 그 파일을 가지고 A
와 C
적은 기가보다, 그것의 모양에 의해 하나의 비디오입니다.
폴더 자체의 총 디스크 사용량에는 50Gb가 고려되지 않았지만 컴퓨터의 전체 디스크 공간은 동일하게 유지되었습니다. 파일이 삭제되지 않았다고 생각합니까?
어떤 도움을 주셔서 감사합니다 🙂
편집 : 파일이 실제로 사라졌고, 마지막으로 쓰여진 파일 만 남았습니다. 디스크 사용 정보를 업데이트하는 데 시간이 걸렸습니다. 이야기의 도덕은 전에 모의 파일에서 스크립트를 실행하십시오!
답변
이것이 문제라고 생각합니다. 디렉토리 A, B, C … Z를 작성해야합니다. 그렇게하면 mv
명령이 파일을 해당 디렉토리로 이동해야합니다.
그러나 그렇지 않은 경우 mv
명령은 파일을 이름이 A, B, C … 인 파일로 이동하며 이것이 당신이 한 것이라고 생각합니다.
셸 스크립트를보다 안전하게하려면 이동을 시작하기 전에 디렉토리가없는 경우 디렉토리를 작성해야합니다.
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)
for dir in "${dirs[@]}"
do
mkdir -p $dir
done
더 안전한 것을 원한다면 옵션 mv
과 함께 사용할 수도 있습니다-i
-i, --interactive
prompt before overwrite
답변
@Sudodus는 이미 무엇이 잘못되었는지 설명 했지만 다음에 더 간단한 스크립트 버전을 소개합니다.
for letter in {a..z}; do
dir=${letter^}
mkdir -p -- "$dir"
mv -- "$letter"* "${letter^^}"* "$dir"/
done
설명
-
for letter in {a..z}; do
: 와{a..z}
사이의 모든 소문자로 확장됩니다 .a
z
$ echo {a..z} 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
따라서 모든 소문자를 반복하여 각을로 저장합니다
$letter
. -
dir=${letter^}
: 구문${var^^}
은$var
대문자로 된 첫 번째 문자 가있는 변수의 내용을 반환합니다 (이 문자 는 하나만 있기 때문에 필요한 전부입니다). 경우에 따라서,$letter
이다a
, 그 다음${letter^^}
이며A
, 따라서$dir
현재의 대문자 버전이 될 것입니다$letter
. mkdir -p -- "$dir"
: 디렉토리를 만듭니다. 이미 존재하면 아무 것도하지 마십시오 (-p
). 는--
옵션의 끝을 의미 하고,로 시작하는 이름을 방지하는 데 유용합니다-
.mv -- "$letter"* "${letter^}"* "$dir"
: 모든 파일 (또는 디렉토리)을 관련 대상으로 이동하십시오.
이것의 문제점은 가지고있는 디렉토리를 이동할 것입니다. 아직 존재하지 않거나 대상 디렉토리로 이동하려고 시도하지만 대상 디렉토리가 아닌 기존 디렉토리는 이동하므로 대상 디렉토리는 이동하지 않습니다.
이것이 문제라면, 다음과 같이해야합니다 :
for file in *; do
if [[ ! -d "$file" ]]; then
letter="${file:0:1}"
dir="${letter^}"
mkdir -p -- "$dir"
mv -- "$file" "$dir"/
fi
done
답변
많은 반복을 생성하는 사전 배열에 대해 모든 파일을 검사하는 대신 패턴과 파일을 일치시킬 수 있습니다.
매우 기본적인 정렬 :
#!/bin/bash
videos=./videos
sorted=./sorted
# sort types link,move.
sort_type=link
find "$videos" -maxdepth 1 -type f \
\( -name '*.avi' -o -name '*.mkv' -o -name '*.mp4' \) -print0 |
while IFS= read -r -d ''; do
b=$(basename "$REPLY")
c=${b::1}
case $c in
[a-zA-Z]) label=${c^} ;; [0-9]) label="0-9" ;; *) label="_" ;;
esac
[[ ! -d "$sorted/$label" ]] && mkdir -p "$sorted/$label"
if [[ -L $sorted/$label/$b ]] || [[ -e $sorted/$label/$b ]]; then
echo "File/link: '$b' exists, skipping."
continue
fi
case $sort_type in
link)
ln -rfst "$sorted/$label" -- "$REPLY"
;;
move)
mv -t "$sorted/$label" -- "$REPLY"
;;
esac
done
답변
.bashrc의 보호 :
alias mv="mv -n --backup=numbered"
답변
기록을 위해 mv
기존 파일 덮어 쓰기 를 중지 하는 몇 가지 방법 :
-
디렉토리로 이동하려면 대상에 슬래시를 추가하십시오 (예 :
mv "$file" "$dir"/
대신 사용)mv "$file" "$dir"
. 경우$dir
존재하지 않거나 디렉토리지지 않습니다,mv
불평 할 것이다 :$ touch a $ mv a z/ mv: cannot move 'a' to 'z/': Not a directory $ touch z $ mv a z/ mv: failed to access 'z/': Not a directory
이것은 시스템 호출을하는 것처럼 보이
rename("a", "z/")
므로 누군가가 같은 파일 세트를 동시에 처리하는 경우에 대비하여 점검 시점부터 사용 시점까지의 취약점으로부터 안전해야합니다. -
또는을 사용하십시오
mv -t "$dir" "$file"
. 다시 말하지만$dir
디렉토리가 아닌 경우 불평합니다 . -
-n
기존 파일 덮어 쓰기를 방지 하려면이 옵션을 사용하십시오 .-n, --no-clobber do not overwrite an existing file
첫 번째 파일의 이름을 바꾸는 것을 막지는 않지만 다른 파일과 함께 휴지통에 버리지 않습니다.
이것은 평범한 것처럼 보이
rename()
므로 동시 처리로 안전하지 않을 수 있습니다.renameat2()
덮어 쓰기를 방지하기 위해 플래그를 지원하는 것이 있습니다 .
답변
분명히 당신의 경우는 아니지만, 당신이 할 수 있고 파일을 잃지 않을 수 있습니다. 이를 위해서는 다음 두 가지 중 하나가 필요합니다.
- 동일한 파일에 대한 하나 이상의 ‘하드 링크’가 파일 시스템의 다른 곳에 존재합니다.
- 하나 이상의 프로세스에 파일이 열려 있습니다
유닉스 파일 시스템은 하나 이상의 디렉토리 항목 이 정확히 같은 파일 내용 을 참조 할 수있게 합니다 . 이것을 ‘ 하드 링크 ‘ 라고합니다 . 일반 (소프트 / 심볼릭) 옵션 없이ln
명령을 사용하여 하드 링크를 만들 수 있습니다 . 파일 내용에 대한 하나 이상의 하드 링크가 존재하는 한 파일 시스템에서이를 재사용하지 않습니다.-s
참고로, 권한은 일반적으로 디렉토리 항목이 아닌 파일 내용에 적용됩니다. 일반 사용자는 때때로 소유 한 파일을 삭제할 수는 root
있지만 쓸 수는 없습니다. 삭제 작업은 파일 자체가 아니라 폴더를 수정합니다. )
파일 시스템은 또한 적어도 하나의 프로세스가 파일을 연 경우에만 파일 내용을 재사용하지 않습니다. 디렉토리 항목이 존재하지 않더라도 파일 시스템은 프로세스가 열릴 때까지 여유 공간을 고려하지 않습니다. 이 파일은 복구 할 수있는 가상 파일 시스템에서 /proc/<pid>/fd
에 의해 root
한 파일이 열린 상태로 유지한다. (@fluffysheap 감사합니다.)