そのため、私は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
を取得しました。これらはGB未満であり、見た目は1つのビデオです。
フォルダー自体の合計ディスク使用量に含まれていない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
の内容を最初の文字を大文字にして返します(これにはone文字しか含まれていないため、これで十分です)。したがって、$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()
があります。)
明らかにあなたには当てはまりませんが、これを行うことができ、ファイルを失わない可能性があります。これには、次の2つの条件のいずれかが当てはまる必要があります。
Unixファイルシステムでは、複数のディレクトリエントリがまったく同じファイルコンテンツ。これは「 ハードリンク 」と呼ばれます。 ln
コマンドを使用してハードリンクを作成できますなし共通-s
(ソフト/シンボリック)オプション。ファイルコンテンツへのハードリンクが少なくとも1つ存在する限り、それはファイルシステムによって再利用されません。
(注意:アクセス許可は通常、ディレクトリエントリではなくファイルコンテンツに適用されます。これが、通常のユーザーがroot
が所有するファイルを削除できるが、書き込みできない場合がある理由です。削除操作により、フォルダが変更されます。 、ファイル自体ではありません。)
また、ファイルシステムは、少なくとも1つのプロセスがファイルを開いている限り、ファイルの内容を再利用しません。ディレクトリエントリが存在しない場合でも、ファイルシステムは、開かれているプロセスがなくなるまで、空き領域とは見なしません。ファイル リカバリ可能 仮想ファイルシステムから/proc/<pid>/fd
by root
ファイルが開いたままである限り。 (@fluffysheapに感謝します。)