我有一个findn
功能:
findn () {
find . -iname "*$1*"
}
使用此函数有一个缺点,如果文件名包含空格,我无法使用-print0 | xargs -0 command
(我正在使用 mac)以下findn filename
扩展 find 命令的功能。
那么,有没有什么办法可以同时保留方便-iname "*$1*"
又实用的功能呢?| xargs command
我正在考虑使用别名来做到这一点,但它不一定是别名。
答案1
您的解决方案适用于xargs
:
$ echo "foo bar one" > foobarone
$ echo "foo bar two" > fooBARtwo
$ findn "bar"
./fooBARtwo
./foobarone
$ findn "bar" | xargs cat
foo bar two
foo bar one
或者我有什么遗漏的吗?
如果你稍微修改一下你的函数,你可以在你的find
命令中添加额外的参数:
findn () {
local name=$1
shift
find . -iname "*$name*" "$@"
}
例子:
$ findn bar ! -name '*two' -print0 | xargs -0 cat
foo bar one
答案2
GNUfind
或兼容的一种方法(-iname
无论如何已经是 GNU 扩展)可以将函数定义为:
findn() (
if [ -t 1 ]; then # if the output goes to a terminal
action=-print # simple print for the user to see
else
action=-print0 # NUL-delimited records so the output can be post-processed
fi
first=true
for arg do
if "$first"; then
set -- "$@" '('
first=false
else
set -- "$@" -o
fi
set -- "$@" -iname "*$arg*"
shift
done
"$first" || set -- "$@" ')'
exec find . "$@" "$action"
)
然后您可以将其用作:
findn foo bar
到看包含foo
或的文件名bar
(如果需要,请将其更改为上面的文件名,而不是包含两者的文件-o
名-a
foo
和 bar
)。
和:
findn foo bar | xargs -r0 cat
如果您想对 . 找到的每个文件应用命令findn
。
对于兼具这两种功能的变体和和不是:
findn() (
if [ -t 1 ]; then # if the output goes to a terminal
action=-print # simple print for the user to see
else
action=-print0 # NUL-delimited records so the output can be post-processed
fi
first=true
for arg do
if "$first"; then
set -- "$@" '('
first=false
else
set -- "$@"
fi
if [ "$arg" = ! ]; then
set -- "$@" !
else
case $arg in
(*[][*?\\]*)
# already contains wildcard characters, don't wrap in *
set -- "$@" -iname "$arg"
;;
(*)
set -- "$@" -iname "*$arg*"
;;
esac
fi
shift
done
"$first" || set -- "$@" ')'
exec find . "$@" "$action"
)
进而:
findn foo bar ! baz
foo
对于同时包含andbar
和 not的文件名baz
。
在该变体中,我还这样做了,如果参数包含通配符,则按原样采用,因此您可以执行以下操作:
findn foo ! 'bar*'
查找不存在的文件开始与酒吧。如果您使用的是zsh
shell,则可以创建一个别名:
alias findn='noglob findn'
要禁用该命令的通配符,您可以编写:
find foo ! bar*
您可能希望将其作为一个脚本(这里一个sh
脚本就足够了,因为该语法是 POSIX)而不是一个函数,这样就可以从任何地方调用它,而不仅仅是您的 shell。