对使用 find 命令找到的每个文件运行 Bash 函数

Aar*_*nke 2 bash find

我目前有这个命令,它成功地在自己的行上打印每个文件名:

find . -exec echo {} \;
Run Code Online (Sandbox Code Playgroud)

我试图分割逻辑,以便find命令执行一个函数。基于这个问题我尝试过:

my_function() {
    echo $1
}
export -f my_function
find . -exec bash -c 'my_function "$@"' bash {} +
Run Code Online (Sandbox Code Playgroud)

然后我得到这个输出:

.
Run Code Online (Sandbox Code Playgroud)

我也尝试替换$@$*,但这会导致$1每个文件都没有换行符。我想运行检查每个文件的逻辑,所以我想$1一次只检查一个文件。我尝试通过空格分割输出,for file in $1但这对于文件名中包含空格的文件不起作用。如何为命令找到的每个文件运行 Bash 函数find

编辑:这是我正在使用的整个脚本。看起来效果很好。

# Ensures that non-csproj text files are formatted with LF line endings.
format() {
    for pathname do
        if [[ $pathname == *"git"* ]]; then
            continue
        elif [[ $pathname == *"csproj"* ]]; then
            continue
        fi
        dos2unix $pathname
    done
}
export -f format
find . -exec bash -c 'format "$@"' bash {} \;
Run Code Online (Sandbox Code Playgroud)

Kus*_*nda 5

dos2unix --newline在当前目录中及其下的每个常规文件上运行,请避免名称包含字符串的任何文件git

find . -type f ! -name '*git*' -exec dos2unix --newline {} +
Run Code Online (Sandbox Code Playgroud)

也就是说,找到名称与模式不匹配的所有常规文件*git*,并dos2unix --newline一次尽可能大批量地运行所有这些文件。更改! -name '*git*'! -path '*git*'以避免路径名包含该字符串的任何文件git(例如.git目录中的文件)。

要明确避免任何目录,但要包含其名称中.git可能包含的任何其他内容:git

find . -name .git -prune -o -type f -exec dos2unix --newline {} +
Run Code Online (Sandbox Code Playgroud)

find即使.git输入使用-prune从搜索树中删除此类路径调用的任何目录,也会停止形式。


在编辑问题之前回答:

您的函数仅打印出其第一个参数。点是您与 一起使用的顶级搜索路径find。它会通过,因为您没有对目录条目进行任何特定的过滤(例如,-type f仅适用于常规文件,或-name,或任何其他类型的find测试)。

如果您希望函数打印其每个参数,请使用

find . -type f ! -name '*git*' -exec dos2unix --newline {} +
Run Code Online (Sandbox Code Playgroud)

让我们printf打印每个参数并在中间换行,或者

find . -name .git -prune -o -type f -exec dos2unix --newline {} +
Run Code Online (Sandbox Code Playgroud)

它循环遍历参数并printf为每个参数调用一次。

如果您调用如下函数,则预计可以正常工作

my_function "$@"
Run Code Online (Sandbox Code Playgroud)

从您的内联bash -c脚本中。扩展"$@"为给予脚本的所有参数,单独引用。

另一种方法是将循环移至bash -c脚本中:

for pathname do
    my_function "$pathname"
done
Run Code Online (Sandbox Code Playgroud)

然后有

my_function() {
    printf '%s\n' "$@"
}
Run Code Online (Sandbox Code Playgroud)

这将明确地执行您所说的操作,即为每个路径名调用该函数一次。

find命令看起来像

my_function() {
    for pathname do
        printf '%s\n' "$pathname"
    done
}
Run Code Online (Sandbox Code Playgroud)

或者,可以说更具可读性,

my_function "$@"
Run Code Online (Sandbox Code Playgroud)

顺便说一句,这与

for pathname do
    my_function "$pathname"
done
Run Code Online (Sandbox Code Playgroud)

.不会被处理。使用它,您不必导出您的my_function函数。

通过函数内部的循环(如本答案中的前两段代码),这将被缩短为

my_function () {
    printf '%s\n' "$1"
}
Run Code Online (Sandbox Code Playgroud)