1

我的根文件夹结构是这样的:

我的家人 - 假期
我的生日[15.11]
姓名-姓名[1]
名称1
名称2
...

现在,我希望每个包含文件的.info文件夹都移动到另一个目录。

这是我的代码:

#!/bin/sh

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

回声仅用于测试。我发现每次一个非转义字符的名字if都是失败的。我怎样才能解决这个问题?

4

3 回答 3

6

Bash 希望你引用你的变量。

#!/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目录消失了,您将得到一个错误,而不是默默地将第一个 $folder 重命名为 Finished,然后将所有其他匹配项移动到第一个匹配项中。

另请注意,我正在使用printf一些调试输出,以防万一您$folder的 s 以连字符开头。

更新 #1:您现在可以使用该-v选项控制调试。

更新#2:我刚刚意识到你正在检查 的存在*.info,从字面上看。笔记:

ghoti@pc ~$ mkdir foo
ghoti@pc ~$ touch foo/\*.info
ghoti@pc ~$ 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 ..
ghoti@pc ~$ [[ -e "foo/*.info" ]] && echo yes
yes
ghoti@pc ~$ mv foo/\*.info foo/bar.info
ghoti@pc ~$ [[ -e "foo/*.info" ]] && echo yes
ghoti@pc ~$

如果您真正想要找到的是“任何以 .info 结尾的文件”,那么[[ -e这不是要走的路。在我对这个答案进行更多工作之前,请确认。:)

更新#3

如果文件夹包含任何 .info 文件,这是一个找到移动文件夹的版本。请注意,这不会grep的输出ls

[ghoti@pc ~/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
[ghoti@pc ~/tmp1]$ find . -print
.
./doit
./baz
./foo
./foo/bar.info
./Finished
[ghoti@pc ~/tmp1]$ ./doit -v
Finished ... skipped
baz ... skipped
doit ... skipped
foo -> ./Finished/foo
[ghoti@pc ~/tmp1]$ 
于 2012-08-08T11:25:03.537 回答
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. 实际上,这不太可能是一个重大问题。如果这是一个问题,您将不想为此使用 shell,尽管您可以这样做:

#!/bin/sh

for dir in *; do
    for f in "$dir"/*; do
        case "$f" in 
            *.info) mv "$dir" ./Finished; break;;
        esac
    done
done
于 2012-08-08T16:15:00.147 回答
-1

Try this:

    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
于 2012-08-08T11:22:30.043 回答