Bash
根據副檔名對文件進行排序
我製作了一個腳本,它將根據文件的副檔名對文件進行排序並將它們放在正確的文件夾中。例如,放置
abc.jpg
在目錄中jpg
。#!/bin/bash #this script sorts files according to their extensions oldIFS=$IFS IFS=$'\n' (find . -type f) > /tmp/temp for var in `cat /tmp/temp` do name=`basename "$var"` ext=`echo $name | cut -d'.' -f2- | cut -d'.' -f2- | cut -d'.' -f2- | cut -d'.' -f2- | cut -d'.' -f2- | cut -d'.' -f2- | cut -d'.' -f2-` mkdir -p $ext mv "$var" $ext/ 2> /dev/null done IFS=$oldIFS
這個腳本的問題:
- 涉及到使用IFS,據說盡量避免使用IFS
- 它不會對沒有文件副檔名的文件進行排序
- 它會對名為 bz 的文件夾中的 abc.tar.bz 等文件進行排序,但是這樣的文件應該放在 tar.bz 文件夾中
- 見我腳本的第 9 行;如果任何文件包含更多沒有。點數(以其名稱)比沒有。腳本中的of
cut -d'.' -f2-
比 if 將導致在擴展部分中採用文件名。
例如,一個名為的文件i.am.live.in.india.and.i.study.computer.science.txt
將被放置在名為的文件夾中study.computer.science.txt
您還可以建議任何調整以使此腳本更小更整潔。
雖然辨識擴展的一般問題很難,但您可以稍微清理一下腳本:
- 告訴
find
只考慮帶有副檔名的文件:-iname '*.*'
- 使用
awk
而不是cut
自己:- 使用腳本,然後告訴
find
執行該腳本。因此:一個名為的腳本,比如說
move.sh
:#! /bin/bash for i do ext=/some/where/else/$(awk -F. '{print $NF}' <<<"$i") mkdir -p "$ext" mv "$i" "$ext" done
然後執行
find
:find . -name '*.*' -type f -exec move.sh {} +
這存在您無法在文件夾中重新排列的問題,因此您可以使用
xargs
:find . -name '*.*' -type f -print0 > /tmp/temp xargs -0 move.sh < /tmp/tmp
我不太確定所涉及的效率,但另一種方法是獲取所有副檔名,然後一口氣移動所有涉及的文件。
就像是:
find . -name '*.*' -type f -print0 | sed -z 's/.*\.//g' | sort -zu > /tmp/file-exts
這應該會為您提供唯一文件副檔名的列表。然後我們的
move.sh
將看起來像:#!/bin/bash for i do mkdir -p "$i" find . -name "*.$i" -type f -exec mv -t "$i" {} + done
我們將執行它:
xargs -0 move.sh < /tmp/file-exts
我在這篇文章中做了很多假設,例如
sed
和sort
支持-z
(允許他們使用 NUL 終止的行find
並xargs
茁壯成長)。
遞歸到子目錄
解析的輸出
find
是不可靠的。如果文件名中有換行符怎麼辦?使用find … -exec …
,這保證了可靠的處理。find . -type f -exec sh -c '…' {} \;
shell 片段
…
接收$0
. 請注意,這是一個單獨的 shell 程序,它不會從祖父腳本繼承變數或函式。您可以通過使用相同的 shell 子程序來處理多個文件來加快處理速度。find . -type f -exec sh -c 'for x; do … done' _ {} +
這一次,在循環內部,文件名在變數
x
.拆分文件名
呼叫諸如 , 等外部實用程序
sed
是cut
脆弱的:您必須非常小心,以免破壞某些文件名。您不需要:shell 的內置字元串處理功能足以滿足您在此處執行的操作。給定一個文件名$x
:directory=${x%/*} basename=${x##*/} extension=… if [ -n "$extension" ]; then mkdir -p "$directory/extension" mv "$x" "$directory/extension" fi
副檔名
文件的副檔名是什麼?它是
.
名稱中的一個之後的部分。沒有標准說明是哪一個。foo.tar.gz
在或之類的情況下,由您決定您認為是副檔名的內容bar-1.2
。這是一些範常式式碼,它考慮了嵌套的常見壓縮擴展,並且要求擴展包含一個字母,因此
foo-1.2.tar.gz
被認為具有擴展tar.gz
.extension= while case "${basename##*.}" in gz|bz2|xz) extension=.${basename##*.}$extension;; # stackable extension *) false;; do basename=${basename%.*} done case "${basename##*.}" in "$basename") :;; # no . ==> no extension *[!0-9A-Za-z]*) :;; # only allow alphanumeric characters *[A-Za-z]*) extension=${basename##*.}$extension;; # non-stackable extension *) false;; # require at least one letter esac extension=${extension#.}