Shell-Script

我該如何改進這個根據副檔名對文件進行排序的腳本?

  • January 19, 2020

我有一個小腳本,它會簡單地瀏覽我的下載文件夾,然後根據副檔名對文件進行排序。

我怎樣才能使這個更清潔/更好?我想簡單地維護一個副檔名和相應目錄的列表,並讓命令使案例如 for 循環執行,所以我不必每次想要添加副檔名時都添加新行。

現在的腳本:

#!/bin/sh

LOCKFILE=/tmp/.hiddensync.lock

if [ -e $LOCKFILE ]
       then
       echo "Lockfile exists, process currently running."
       echo "If no processes exist, remove $LOCKFILE to clear."
       echo "Exiting..."

       exit
fi

touch $LOCKFILE
timestamp=`date +%Y-%m-%d::%H:%M:%s`
echo "Process started at: $timestamp" >> $LOCKFILE

## Move files to various subfolders based on extensions
find ~/Downloads -maxdepth 1 -name "*.pdf" -print0 | xargs -0 -I % mv % ~/Downloads/PDF/
find ~/Downloads -maxdepth 1 -name "*.opm" -print0 | xargs -0 -I % mv % ~/Downloads/OPM/
find ~/Downloads -maxdepth 1 -name "*.yml" -print0 | xargs -0 -I % mv % ~/Downloads/YML/
find ~/Downloads -maxdepth 1 -name "*.css" -print0 | xargs -0 -I % mv % ~/Downloads/CSS/
find ~/Downloads -maxdepth 1 -name "*.tar.gz" -print0 | xargs -0 -I % mv % ~/Downloads/archives/
find ~/Downloads -maxdepth 1 -name "*.zip" -print0 | xargs -0 -I % mv % ~/Downloads/archives/
find ~/Downloads -maxdepth 1 -name "*.jpg" -print0 | xargs -0 -I % mv % ~/Downloads/Pictures/
find ~/Downloads -maxdepth 1 -name "*.png" -print0 | xargs -0 -I % mv % ~/Downloads/Pictures/
find ~/Downloads -maxdepth 1 -name "*.tiff" -print0 | xargs -0 -I % mv % ~/Downloads/Pictures/
find ~/Downloads -maxdepth 1 -name "*.pm" -print0 | xargs -0 -I % mv % ~/Downloads/Perl/
find ~/Downloads -maxdepth 1 -name "*.xls*" -print0 | xargs -0 -I % mv % ~/Downloads/Excel/
find ~/Downloads -maxdepth 1 -name "*.doc*" -print0 | xargs -0 -I % mv % ~/Downloads/Word/

echo "Task Finished, removing lock file now at `date +%Y-%m-%d::%H:%M:%s`"
rm $LOCKFILE

當一個目的地有多個擴展時,您可以將更多邏輯放入find指令中:

find ~/Downloads -maxdepth 1 \( -name "*.tar.gz" -o -name "*.zip" \) -print0 | xargs -0 -I % mv % ~/Downloads/archives/

而且您不需要通過管道傳輸到 xargs:

find ~/Downloads -maxdepth 1 \( -name "*.tar.gz" -o -name "*.zip" \) -exec mv -t ~/Downloads/archives/ {} +

既然你有-maxdepth 1,你真的需要find嗎?

shopt -s nullglob
cd ~/Downloads
mv -t archives/ *.tar.gz *.zip
mv -t Pictures/ *.jpg *.png *.tiff
# etc

如果沒有要移動的文件,這種方法會發出一些錯誤。您可以通過以下方式解決此問題:

shopt -s nullglob
movefiles() {
   local dest=$1
   shift
   if (( $# > 0 )); then
       mkdir -p "$dest"
       mv -t "$dest" "$@"
   fi
}
cd ~/Downloads
movefiles PDF/      *.pdf
movefiles OPM/      *.opm
movefiles YML/      *.yml
movefiles CSS/      *.css
movefiles archives/ *.zip *.tar.gz
movefiles Pictures/ *.jpg *.png *.tiff
movefiles Perl/     *.pm
movefiles Excel/    *.xls*
movefiles Word/     *.doc*

筆記:

  • 如果沒有 nullglob,如果沒有文件與模式匹配,則函式將接收模式作為字元串。

    • 例如,如果沒有 pdf 文件,shell 將執行movefiles PDF/ "*.pdf"
  • 對於 nullglob,如果沒有匹配項,則 shell 從命令中刪除模式:movefiles PDF/

  • 這就是我檢查參數數量的原因:如果沒有文件匹配,那麼在移動之後,$# 為零,因此沒有任何東西可以移動。

引用自:https://unix.stackexchange.com/questions/562461