当找不到物品时,带有计数器的bash循环的数量为1。为什么?

发布于 2025-02-07 10:23:58 字数 1186 浏览 0 评论 0原文

在下面的功能中,只要在$ dt_files中找到一个项目,就可以正常工作。如果该文件夹的发现为空,则计数器的计数为1而不是0。我不确定我缺少什么。

脚本在这里所做的是1)制作一个包含所有父文件夹的变量。 2)循环浏览每个文件夹,每个文件夹在每个文件夹中,并列出包含字符串“ -dt-”的所有文件的列表。 3)如果它找到一个不以“ .tif”结尾的文件,则它将复制DT文件并将.TIF扩展程序放置在其上。非常简单。

我计算循环确实创建一个带有“ .tif”扩展名的新文件的次数。

因此,我不确定为什么有时会得到1个。

function create_tifs()
{
    IFS=$'\n'

    # create list of main folders
    LIST=$( find . -maxdepth 1 -mindepth 1 -type d )

    for f in $LIST
    do
        echo -e "\n${OG}>>> Folder processed: ${f} ${NONE}"
        cd ${f}

            DT_FILES=$(find . -type f -name '*-DT-*' | grep -v '.jpg')
            if (( ${#DT_FILES} ))
            then
                count=0
                for b in ${DT_FILES}
                do
                    if  [[ "${b}" != *".tif" ]]
                    then
#                        cp -n "${b}" "${b}.tif"
                        echo -e "TIF created ${b} as ${b}.tif"
                        echo
                       ((count++))
                    else
                        echo -e "TIF already done ${b}"

                    fi
                done
            fi

            echo -e "\nCount = ${count}"
}

In the function below my counter works fine as long as an item is found in $DT_FILES. If the find is empty for that folder the counter gives me a count of 1 instead of 0. I am not sure what I am missing.

What the script does here is 1) makes a variable containing all the parent folders. 2) Loop through each folder, cd inside each one and makes a list of all files that contain the string "-DT-". 3) If it finds a file that doesn't not end with ".tif", it then copy the DT files and put a .tif extension to it. Very simple.

I count the number of times the loop did create a new file with the ".tif" extension.

So I am not sure why I am getting a count of 1 at times.

function create_tifs()
{
    IFS=
\n'

    # create list of main folders
    LIST=$( find . -maxdepth 1 -mindepth 1 -type d )

    for f in $LIST
    do
        echo -e "\n${OG}>>> Folder processed: ${f} ${NONE}"
        cd ${f}

            DT_FILES=$(find . -type f -name '*-DT-*' | grep -v '.jpg')
            if (( ${#DT_FILES} ))
            then
                count=0
                for b in ${DT_FILES}
                do
                    if  [[ "${b}" != *".tif" ]]
                    then
#                        cp -n "${b}" "${b}.tif"
                        echo -e "TIF created ${b} as ${b}.tif"
                        echo
                       ((count++))
                    else
                        echo -e "TIF already done ${b}"

                    fi
                done
            fi

            echo -e "\nCount = ${count}"
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

坏尐絯 2025-02-14 10:23:58

我无法再现您的问题,但是您的代码包含几个可疑构造。以下是重构,可能还可以消除您遇到的任何问题。

#!/bin/bash

# Don't use non-portable function definition syntax
create_tifs() {
    # Don't pollute global namespace; don't attempt to parse find output
    # See also https://mywiki.wooledge.org/BashFAQ/020
    local f
    for f in ./*/; do
        # prefer printf over echo -e
        # print diagnostic messages to standard error >&2
        # XXX What are these undeclared global variables?
        printf "\n%s>>> Folder processed: %s %s" "$OG" "$f" "$NONE" >&2

        # Again, avoid parsing find output
        find "$f" -name '*-DT-*' -not -name '*.jpg' -exec sh -c '
            for b; do
                if  [[ "${b}" != *".tif" ]]
                then
#                   cp -n "${b}" "${b}.tif"
                    printf "TIF created %s as %s.tif\n" "$b" "$b" >&2
                    # print one line for wc
                    printf ".\n"
                else
                    # XXX No newline, really??
                    printf "TIF already done %s" "$b" >&2
                fi
            done
        fi' _ {} +
    # Missing done!
    done |
    # Count lines produced by printf inside tif creation
    wc -l |
    sed 's/.*/Count = &/'
}

可以通过使用查找./*/而不是通过f来进一步简化这。同样,您可以添加-not -name'*.tif',但是随后您无法为这些打印“ TIF已经完成”。

切线也许也可以参见正确的bash and shell script脚本可变资本化;为私人变量使用较低的外壳。

在您的实际消息(例如第一个printf)之前打印newline 是一个奇怪的对抗图案,尤其是当您不这样做时。通常的安排是在​​每个发出的消息的末尾放置一个新线。

I can't repro your problem, but your code contains several dubious constructs. Here is a refactoring might coincidentally also remove whatever problem you were experiencing.

#!/bin/bash

# Don't use non-portable function definition syntax
create_tifs() {
    # Don't pollute global namespace; don't attempt to parse find output
    # See also https://mywiki.wooledge.org/BashFAQ/020
    local f
    for f in ./*/; do
        # prefer printf over echo -e
        # print diagnostic messages to standard error >&2
        # XXX What are these undeclared global variables?
        printf "\n%s>>> Folder processed: %s %s" "$OG" "$f" "$NONE" >&2

        # Again, avoid parsing find output
        find "$f" -name '*-DT-*' -not -name '*.jpg' -exec sh -c '
            for b; do
                if  [[ "${b}" != *".tif" ]]
                then
#                   cp -n "${b}" "${b}.tif"
                    printf "TIF created %s as %s.tif\n" "$b" "$b" >&2
                    # print one line for wc
                    printf ".\n"
                else
                    # XXX No newline, really??
                    printf "TIF already done %s" "$b" >&2
                fi
            done
        fi' _ {} +
    # Missing done!
    done |
    # Count lines produced by printf inside tif creation
    wc -l |
    sed 's/.*/Count = &/'
}

This could be further simplified by using find ./*/ instead of looping over f but then you don't (easily) get to emit a diagnostic message for each folder separately. Similarly, you could add -not -name '*.tif' but then you don't get to print "tif already done" for those.

Tangentially perhaps see also Correct Bash and shell script variable capitalization; use lower case for your private variables.

Printing a newline before your actual message (like in the first printf) is a weird antipattern, especially when you don't do that consequently. The usual arrangement would be to put a newline at the end of each emitted message.

冷夜 2025-02-14 10:23:58

如果您有bash 4.0或以后,则可以使用globstar而不是(容易出错)查找。尝试此 shellCheck -clean Code:

#! /bin/bash -p

shopt -s dotglob extglob nullglob globstar

function create_tifs
{
    local dir dtfile
    local -i count
    for dir in */; do
        printf '\nFolder processed: %s\n' "$dir" >&2

        count=0
        for dtfile in "$dir"**/*-DT-!(*.jpg); do
            if [[ $dtfile == *.tif ]]; then
                printf 'TIF already done %s\n' "$dtfile" >&2
            else
                cp -v -n -- "$dtfile" "$dtfile".tif
                count+=1
            fi
        done
        printf 'Count = %d\n' "$count" >&2
    done

    return 0
}
  • shopt -s shopt -s ...启用一些bash代码要求的设置:
    • dotglob使Globs能够匹配以开头的文件和目录。 查找默认情况下显示此类文件。
    • extglob启用“扩展地球布”(包括!(*。jpg)等模式)。参见 extglob glob“ rel =“ nofollow noreferrer”> glob -Greg的Wiki 。
    • nullglob使Globs在没有匹配的情况下将其扩展到无与伦比(否则它们扩展到Glod模式本身,这几乎在程序中从来都不是有用的)。
    • globstar启用**可以通过目录树递归匹配路径。
  • 请注意,globstar在4.3之前的bash版本中可能是危险的,因为它遵循符号链接,可能导致多次处理相同的文件或目录,或者陷入周期。
  • -v带有cp的选项使其打印其所做的详细信息。您可能更喜欢丢弃该选项,而是打印另一种消息格式。
  • 请参阅被接受的且极好的答案,对为什么printf胜于echo? 为什么要解释为什么我使用<<代码> printf 而不是echo
  • 我没有使用CD,因为它通常会导致程序中的问题。

If you've got Bash 4.0 or later you can use globstar instead of (the error-prone) find. Try this Shellcheck-clean code:

#! /bin/bash -p

shopt -s dotglob extglob nullglob globstar

function create_tifs
{
    local dir dtfile
    local -i count
    for dir in */; do
        printf '\nFolder processed: %s\n' "$dir" >&2

        count=0
        for dtfile in "$dir"**/*-DT-!(*.jpg); do
            if [[ $dtfile == *.tif ]]; then
                printf 'TIF already done %s\n' "$dtfile" >&2
            else
                cp -v -n -- "$dtfile" "$dtfile".tif
                count+=1
            fi
        done
        printf 'Count = %d\n' "$count" >&2
    done

    return 0
}
  • shopt -s ... enables some Bash settings that are required by the code:
    • dotglob enables globs to match files and directories that begin with .. find shows such files by default.
    • extglob enables "extended globbing" (including patterns like !(*.jpg)). See the extglob section in glob - Greg's Wiki.
    • nullglob makes globs expand to nothing when nothing matches (otherwise they expand to the glob pattern itself, which is almost never useful in programs).
    • globstar enables the use of ** to match paths recursively through directory trees.
  • Note that globstar is potentially dangerous in versions of Bash prior to 4.3 because it follows symlinks, possibly leading to processing the same file or directory multiple times, or getting stuck in a cycle.
  • The -v option with cp causes it to print details of what it does. You might prefer to drop the option and print a different format of message instead.
  • See the accepted, and excellent, answer to Why is printf better than echo? for an explanation of why I used printf instead of echo.
  • I didn't use cd because it often leads to problems in programs.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文