【问题标题】:expand bash functions in find's exec parameter在 find 的 exec 参数中展开 bash 函数
【发布时间】:2012-03-16 10:01:00
【问题描述】:

如何让find 在其exec 参数中应用我的shell 定义的函数和别名?

例如,我定义了一个类似于 bzip2 但使用 7z 的函数:

function 7zip() { for f in $@;做 ls -alF "$f"; 7za a -t7z -m0=lzma -mx=9 -mfb=64 -md=64m -ms=on "$f.7z" "$f" && touch -r "$f" "$f.7z" && rm -fv "$f" && ls -alF "$f.7z";完毕; }

当我发现要压缩超过 7 天的文件时:

find . -mtime +7  -name "G*.html"   -execdir  7zip {}  + 

而不是扩展 7zip 它会出错 Command Not Found。

这一切都在一个 shell 脚本中。

【问题讨论】:

  • 总结一些cmets: 1. 在~/.bashrc 中定义和export -f 7zipi 2. 使用find ... -exec bash -c "7zipi {}" +

标签: bash shell find expansion


【解决方案1】:

您可以通过以下方式导出函数定义:

export -f 7zipi

但是使用名称以数字开头的标识符是自找麻烦。尝试将名称更改为合理的名称。 (例如“f7zipi”或“_7zipi”)

【讨论】:

  • 试过了,还是得到find: '7zipi': No such file or directory
  • 已定义,导出-f,也尝试了_版本:find: '_7zipi': No such file or directory
  • 它适用于我,但它只会在该 bash 会话期间有效...要使其永久化,请将函数定义和导出行添加到您的 ~/.bashrc 文件中跨度>
  • 奇怪...它对我不起作用,在 bash v. 3.2.39 和 find (GNU findutils) v. 4.4.0 中。看起来这是 find 的限制,它不接受函数作为 --execdir 参数。
  • @nik Find 没有通过 bash 调用命令。试试 -execdir bash -c 'zipi7 {}' \;
【解决方案2】:

所有这四个命令都可以在函数调用中正常工作。根据需要调整您的查找规范。它们都适合文件名中的空格。就个人而言,我看不出使用另一个 bash 实例的意义,但我已经包含了两个调用 bash 的版本。

IFS=$'\n'; f=($(find /tmp -maxdepth 1 -name "$USER.*")); f7zipi "${f[@]}"

IFS=; find /tmp -maxdepth 1 -name "$USER.*" | while read -r f ;do f7zipi "$f"; done 

IFS=$'\n'; bash -c 'IFS=; f7zipi "$@"' 0 $(find /tmp -maxdepth 1 -name "$USER.*")  

find /tmp -maxdepth 1 -name "$USER.*" -exec bash -c 'IFS=; f7zipi "$@"' 0 {} +;   

接下来是我如何设置函数,在 Ubuntu 10.04 中使用 GNU bash 4.1.5

顺便说一句。您应该在函数中使用local f,以便它不会与调用脚本的同名变量冲突

这正是我添加到我的 ~/.bashrc 中的内容

function f7zipi() { 
    local f
    for f in $@; do 
        ls -alF "$f"
        7za a -si -t7z -m0=lzma -mx=9 -mfb=64 \
        -md=64m -ms=on "$f.7z" < "$f" && 
            touch -r "$f" "$f.7z" && 
            rm -fv "$f" && 
            ls -alF "$f.7z"
    done
}
export -f f7zipi

当我只将上述函数分配给终端的 bash 命令行时,从该命令行运行的脚本在调用该函数时会失败...如果我进一步将 export -f f7zipi 应用于同一命令行.. 那么脚本成功...但是 scipt 仅适用于该特定的命令行会话。

当函数和导出包含在~/bashrc 中时,脚本每次都有效,在任何 bash 会话中..

这是测试脚本

#!/bin/bash
f=/tmp/$USER.abc
g=/tmp/$USER.lmn
rm -fv "$f" "$f".7z
rm -fv "$g" "$g".7z
printf 'abcdefg'>"$f"
printf 'lmnopqr'>"$g"
IFS=$'\n'; f=($(find /tmp -maxdepth 1 -name "$USER.*")); f7zipi "${f[@]}"
exit

【讨论】:

  • 您要说明这对find-execdir-exec 是如何工作的,不是吗?
  • @Marcos,不,是 William Pursell 建议在 subshel​​l 中调用 bash 以回应 Nik O'Lai 的评论....我真的只参与响应 可能的原因的函数调用错误...
  • 我现在添加了 4 种方法来调用函数,其输出来自 find... 两种方法利用 find -exec
  • 感谢您的全面测试!顺便说一句,我切换到我之前的 7zip 函数,该函数通过 not 从 stdin ala &lt; "$f" 压缩来保留内部文件的时间戳。此外,事实证明bzip2 -9v 在处理 1000+ 个 60-400kb 的 html 文件时效果稍好一些。 7z 似乎以许多 MB 的更大/可靠档案击败了它。
【解决方案3】:

作为比我不耐烦的编码员,现在我将其更改为多行:

hitlist=$(find . -mtime +7  -name "G*.html")
7zipi $hitlist |awk ' !x[$0]++'

最后的那个 awk 位顺便说一句,这样输出只打印以前没有见过的行,这样它就不会被无数的行弄乱:

7-Zip (A) 9.20  Copyright (c) 1999-2010 Igor Pavlov  2010-11-18
p7zip Version 9.20 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,2 CPUs)
Compressing  [Content]      
Everything is Ok

NOT 确实是答案;我仍然希望 find 普遍使用我的宏。

【讨论】:

  • 查看我对 William Pursell 答案的评论,这确实需要额外的步骤。
  • @Peter.O 发布您的bash -c 答案,以便我标记为解决方案。那东西已经在我的.bashrc 里了。
  • 我使用的方法没有使用bash -c..我已经发布了,所以你可以将它与你拥有的进行比较。
  • @Marcos 或者只是:7zipi $(find . -mtime +7 -name "G*.html")
【解决方案4】:

似乎不是每个find 都会接受一个函数作为--execdir 的参数。无论是原始形式还是使用export -f,它都不适合我。

但是,如果你用你的函数制作一个脚本,它会起作用

find . -mtime +7 -name "G*.html" -execdir  /path/to/script_7zipi {} +

【讨论】:

  • 是的。我可以坚持使用更便携的bzip2 -9v,或者希望一些包装器脚本最终被打包到 7z 中,以使其更像管道等中使用的传统压缩器。
猜你喜欢
  • 1970-01-01
  • 2017-03-18
  • 1970-01-01
  • 1970-01-01
  • 2011-03-04
  • 2013-12-07
  • 2011-05-18
  • 2022-07-05
  • 1970-01-01
相关资源
最近更新 更多