2012-08-08 79 views
1

我的根文件夾結構是這樣的:使用bash排序文件夾

 
My Family - Holiday 
My Birthday[15.11] 
Name-Name[1] 
Name1 
Name2 
... 

現在,我想其中包含一個.info文件移動到另一個目錄中的每個文件夾。

這裏是我的代碼:

#!/bin/sh 

for folder in * 
do 
    echo $folder 
    if [ -e "$folder/*.info" ] 
    then 
      echo $folder 
      mv $folder ./Finished 
    fi 
done 

的回聲是僅用於測試。 我發現每當一個非轉義字符出現在if失敗的名字中時。我怎樣才能解決這個問題?

+0

認沽'$ folder'引號。即'mv「$文件夾」./ Finished /'。見下文。 – ghoti 2012-08-08 11:22:54

+0

在'mv'中引用你'$ folder'。該命令將是'mv「$文件夾」/完成「 – nshy 2012-08-08 11:23:28

回答

3

主要問題是您不能使用test -e *.info。您可以解析ls的輸出以檢查文件。解析ls存在問題,但它們並不像許多人想象的那麼重要。如果不允許在文件名換行,下面應該工作:

#!/bin/sh 

for dir in *; do 
    if ls -f "$dir" | grep -q '\.info$'; then 
     mv "$dir" ./Finished 
    fi 
done 

請注意,這是至關重要的,沒有文件名中包含一個嵌入式的換行符,因爲這將不正確地識別一個名爲foo.info\nbar文件,如果有一個文件名爲foo.info。事實上,這不太可能是一個重要問題。如果這是一個問題,你會不會想用這個殼,但你可以這樣做:

#!/bin/sh 

for dir in *; do 
    for f in "$dir"/*; do 
     case "$f" in 
      *.info) mv "$dir" ./Finished; break;; 
     esac 
    done 
done 
+0

thx第二個爲我工作:) – demonking 2012-08-08 19:14:42

-1

試試這個:

PATH_TO_FOLDER="/YOUR_FOLDER" 

    for f in `ls $PATH_TO_FOLDER`; 
    do 
     # Check filename 

     if [ $(echo $f | grep -Ec ".info$") -ne 1 ] 
     then 
      echo "We don't care" 
     else 
      ## move the file 
     fi 
    done 
+2

不要這樣做。 [Parsing LS](http://mywiki.wooledge.org/ParsingLs)問題的完美例子。 – ghoti 2012-08-08 11:24:03

+0

爲什麼投票? – TOC 2012-08-08 11:25:15

+0

關於downvotes沒有什麼個人特色。他們只是用來表明答案有缺陷或其他問題。在這種情況下,您會以不安全的方式遍歷文件。你讀過@ghoti給的帖子了嗎? – 2012-08-08 11:41:29

6

猛砸想請你報你的變量。

#!/bin/bash 

if [[ "$1" = "-v" ]]; then 
    Verbose=true 
    vopt="-v" 
    shift 
else 
    Verbose=false 
    vopt="" 
fi 

for folder in *; do 
    $Verbose && printf "%s" "$folder" 
    if [[ -e "$folder/*.info" ]]; then 
      if mv "$vopt" "$folder" ./Finished/; then 
       $Verbose && echo -n " ... done" 
      fi 
    fi 
    $Verbose && echo "" 
done 

請注意,用斜線結束目標目錄是一個好主意。這樣,如果由於某種原因Finished目錄消失,您將得到一個錯誤,而不是默默地將第一個$文件夾重命名爲Finished,然後將所有其他匹配移至第一個匹配。

請注意,我爲某些調試輸出使用了printf,以防您的$folder之一以連字符開頭。

UPDATE#1:您現在已通過-v選項控制調試。

UPDATE#2:我剛剛意識到您正在檢查*.info字面上的存在。注:

[email protected] ~$ mkdir foo 
[email protected] ~$ touch foo/\*.info 
[email protected] ~$ ls -la foo 
total 0 
-rw-r--r-- 1 ghoti ghoti 0 8 Aug 07:45 *.info 
drwxr-xr-x 3 ghoti ghoti 102 8 Aug 07:45 . 
drwx------+ 10 ghoti ghoti 340 8 Aug 07:44 .. 
[email protected] ~$ [[ -e "foo/*.info" ]] && echo yes 
yes 
[email protected] ~$ mv foo/\*.info foo/bar.info 
[email protected] ~$ [[ -e "foo/*.info" ]] && echo yes 
[email protected] ~$ 

如果你真的想找到什麼是「在結尾的.info的任何文件」,然後[[ -e是不是要走的路。在我更多地瞭解這個答案之前,請確認。 :)

更新#3

下面是找到移動你的文件夾,如果該文件夾conains任何.info文件版本。請注意,這是而不是 grep ls的輸出。

[[email protected] ~/tmp1]$ cat doit 
#!/bin/bash 

if [[ "$1" = "-v" ]]; then 
    Verbose=true 
    vopt="-v" 
    shift 
else 
    Verbose=false 
    vopt="" 
fi 

for folder in *; do 

    infofile="$(
     if [[ -d "$folder" ]]; then 
      cd "$folder" 
      for file in *.info; do 
       if [[ -f "$file" ]]; then 
        echo "$file" 
        break 
       fi 
      done 
     fi 
    )" 

    if [[ -f "$folder/$infofile" ]]; then 
     mv "$vopt" "$folder" ./Finished/ 
    elif $Verbose; then 
     printf "%s ... skipped\n" "$folder" 
    fi 

done 
[[email protected] ~/tmp1]$ find . -print 
. 
./doit 
./baz 
./foo 
./foo/bar.info 
./Finished 
[[email protected] ~/tmp1]$ ./doit -v 
Finished ... skipped 
baz ... skipped 
doit ... skipped 
foo -> ./Finished/foo 
[[email protected] ~/tmp1]$ 
+2

+1確實。讓它成爲你的習慣,引用所有變量 – 2012-08-08 11:26:34

+0

hm ..它對我不起作用,當我刪除printf時,我只得到很多空行:/ printf對於調試很有用,但它永遠不會進入if語句 – demonking 2012-08-08 11:35:23

+1

它移動的東西?另一個用於調試的選項是添加一個'-v'選項來移動,所以它會告訴你它何時運行。我已經爲答案添加了更多的調試控制。我希望如果'echo'... done''沒有執行,那是因爲'mv'失敗並且返回了一個錯誤,但是你可能想要包含'else'來調試那個'if條件更完整。 – ghoti 2012-08-08 11:40:27