2016-04-18 22 views
0

我想再次詢問bash。 我想從目錄中隨機獲取文件。例如有如何在bash編程中從目錄中隨機獲取文件

13.525 file in 1 directory。

我是隨機的文件並獲取文件

gr123.adl併爲下一個隨機我想

gr123.adl不被再次選擇的文件。

我應該如何用bash語言實現它?

感謝對您的幫助之前

問候 Gustina MS

+0

我'MV文件dir_already_processed'爲你處理完一個文件,那麼你就無法再得到它。否則你必須維護一個列表(在一個文件或一個shell數組中)。祝你好運。 – shellter

+1

這是一個現實世界的問題嗎?我想不出爲什麼你會需要這個?通常隨機在任何情況下都不是唯一的。 – SaintHax

+0

@SaintHax我懷疑「測試」標記是這個用例的關鍵部分,我可以想象要編寫一個測試,以隨機的順序處理一個目錄中的文件 –

回答

1

你可以嘗試以下方法:

ls | sort -R | while read f; do echo $f; done 

sort -R被洗牌的文件中,while循環確保你得到所有文件1由1

編輯:

如果某些文件中包含控制字符(如\n),你可以試試這個:

OLDIFS=$IFS; IFS=$(echo -en "\b"); for f in $(ls -b | sort -R); do echo "$f"; done; IFS=$OLDIFS 

這改變了輸入字段分隔符\b(其更改爲適合任何沒有任何字符匹配所有文件名)。

ls -b列出帶有控制字符的文件。

for循環有一個接一個的文件。

最後,IFS被設置爲其原始值。

+0

請注意,如果有的話,這將無法正常工作文件的名稱中包含換行符 –

+1

雖然我編輯了帖子以回答您的評論,但我認爲文件名中控制字符的處理方式值得自己去考慮。 – oliv

+0

它經常是這裏討論的主題,並且出現了很多問題。他們通常會鏈接到http://mywiki.wooledge.org/ParsingLs和「不解析ls'的建議」 –

1

如果你真的想這樣做,那麼你需要一個函數,它會帶參數和跟蹤文件。

rand_file() { 
    track=~/${PWD##*/}.rand_file 
    touch $track 

    while read f; do 
     if ! grep -q "$f" $track; then 
     echo $f| tee -a $track 
     break 
     fi 
    done < <(ls |sort -R) 
} 

我們使用一個for循環,所以,如果我們已經得到了在目錄中的所有文件,它乾淨地退出。我們正在跟蹤以該目錄命名的文件,因此如果同名文件在別處,我們不會將它用作以前返回的文件 - 注意,這意味着您必須在PWD中使用它,您可以編寫一些代碼更好,但我現在不打算把這部分敲出來。一旦所有文件都被返回,函數退出並返回任何內容。您可以刪除主目錄中的文件以重置進程。

+0

這不像上面的'while'解決方案那樣安全。這將打破任何'IFS'中的任何字符的文件 –

+0

@EricRenouf而來自oliv的解決方案不符合要求。它不返回文件(它將它們全部返回)。你可以隨時調整IFS,但在bash的測試場景中,我假設你使用的是普通的Linux文件名 - 沒有空格。這些不是從客戶端發送,而是從內部發送的文件。 – SaintHax

+0

@EricRenouf我將把它改爲一個while循環給你。我期望在封閉的測試環境中,您可以避免使用Windows名稱的文件,但是... 請注意引用所有$ track,如果需要,腳本編寫者可以執行此操作。 – SaintHax

2

我可能會希望在另一種語言中做到這一點,如果可能的話,這種語言有更好的處理方式。例如,在python你可以不喜歡它

files = os.listdir('.') 
random.shuffle(files) 
for path in files: 
    # do your code test stuff on path 

具有將返回下一個文件名是強硬的bash做的功能,但如果你只是想以隨機的順序對文件進行操作,我們可以遵循@ shelter的建議並使用數組,並結合在this answer中找到的隨機函數。在這裏,我們將打亂所有文件名中的數組,然後遍歷它們:

shuffle() { 
    local i tmp size max rand 

    # $RANDOM % (i+1) is biased because of the limited range of $RANDOM 
    # Compensate by using a range which is a multiple of the array size. 
    size=${#array[*]} 
    max=$((32768/size * size)) 

    for ((i=size-1; i>0; i--)); do 
     while (((rand=$RANDOM) >= max)); do :; done 
     rand=$((rand % (i+1))) 
     tmp=${array[i]} array[i]=${array[rand]} array[rand]=$tmp 
    done 
} 

array=(*) 
shuffle 

for((i=0; i<${#array[*]}; i++)); do 
    printf "Operating on %s\n" "${array[i]}" 
    # do whatever test makes sense on "${array[i]}" 
done 

如果你真的想將返回「下一個」文件中的函數,我們可以從上面做到這一點有點不同,設置變量我們將用它來保存我們當前的文件名。因此,我們生病像這樣替換for循環在用另一個函數的定義和循環中的底部:

next_file() { 
    if [[ "$array_ind" -ge "${#array[*]}" ]]; then 
     cur="" 
    else 
     cur="${array[array_ind++]}" 
    fi 
} 

array_ind=0 

# now we use next_file whenever we want `cur` to get the next file: 
next_file 
while [[ ! -z "$cur" ]]; do 
    printf -- "--%s--\n" "$cur" 
    next_file 
done