2017-02-28 27 views
0

,我發現這個bash腳本,工程巨大移動X個文件到其他目錄

for file in $(ls -p | grep -v/| tail -241) 
do 
mv $file ../01 
done 

我的bash foo是弱的,基本上如果我的目錄裏面運行將在最後一個241個文件移動到的文件夾/ 01

問題是腳本本身必須在所有文件的目錄中,而且我的當前掛載沒有執行權限。我想要做的是從外部文件夾執行此腳本,例如我的工作目錄/ home/user/

我的當前根目錄位於不同的驅動器/分區上,而不是我想要腳本執行的所有文件上。

for file in **/media/storage1/allfiles** $(ls -p | grep -v/| tail -241) 
do 
mv $file ../01 <this should remain local to /media/storage/ 
done 

**編輯** 我得到這個由環 cd the/directory/I/want/to/be/in前加入這個工作:

例如

cd /media/storage1/allfiles 
for file in $(ls -p | grep -v/| tail -241) 
do 
    mv $file ../01 
done 

更好的問題是:這是正確的方式來做到這一點,還是有正確的方法?

+1

在'for'循環中使用'ls'輸出是不可取的 - 如果你的文件有特殊字符如空格或'*',它將會中斷。否則,你的邏輯聽起來很合理。 – codeforester

+2

這是一個非常明智的方法,儘管你應該考慮爲源目錄名稱和目標目錄名稱(以及要移動的文件數量)使用命令行參數 - 除非所有內容都真正修復。除此之外,如果您不必冒險搞亂製作目錄,測試會變得更容易,因爲您可以在命令行上指定名稱。除文件名(標籤,換行符)外沒有空白或其他恐怖故事......另外,GNU'mv'有一個選項'-t directory',可以用來減少調用'mv'的次數。 –

+0

就像'mv f1 f2 f2 ../ 01'可以正常工作。 '-t'選項的好處是當'mv'使用類似'find -exec mv -t dir {} +'的命令時,其中文件列表必須是最後一個。 – chepner

回答

2

bash,我會盡量避免使用ls。它利用了這樣一個事實,即你並沒有試圖以任何特定的方式對文件進行排序,所以通過路徑名擴展提供的任何順序就足夠了。

cd /media/storage1/allfiles 
# Get *all* regular files in the target directory 
for f in *; do 
    [[ -f $f ]] && files+=("$f") 
done 
# Get the file count 
n=${#files[@]} 
# How many files are we *not* moving 
# Assume n > 241 
keep=$((n - 241)) 
# Move the last 241 files 
mv -- "${files[@]:keep}" ../01 

據推測,241個文件不會長到溢出命令行。


不請自來zsh塞...

zsh使這是一個更容易一些,因爲你可以使外殼做了很多與水珠本身的選擇工作。

mv /media/storage/allfiles/*(.On[1,241]) ../01 

(...)水珠以下是一組限制的文件的列表產生水珠限定符。 .表示只有常規文件應該匹配。 On按名稱以相反順序對列表進行排序(其他排序順序可通過用適當的字符替換n來使用)。 [1,241]將列表限制爲第241個文件;因爲我們按照相反的順序排序,這會給你最後的241個文件。

+0

啊只是一點點背景@chepner 241是因爲我有很多文件和運行我的腳本對他們只使用1核心每個實例運行。所以我把文件吐到20(我有24個內核),然後同時運行程序20次以最大化內核。 。你的腳本很好,只是好奇爲什麼避免使用ls? – chowpay

+1

從技術上講,'ls'不會每行寫一個文件;它寫入由換行符分隔的文件名,並且文件名*可以*(不管它們很少*做* *)包含換行符。這意味着你不能假定一行文本是一個完整的文件名。 – chepner