我有一个目录。这个目录有很多子目录,其中包含html页面和一些c源代码文件,Makefile等。我试图编写的脚本将从一个具有所有这些子目录的目录执行。 以下是您可以看到的目录和文件集
ls
delete.sh lddbus Makefile misc-progs sbull scullc scullp short simple snull usb
include LICENSE misc-modules pci scull sculld scullv shortprint skull tty
其中一些是目录,一些是上面子目录中的文件,还有我想要消除的其他子目录和html页面。 手动方式是进入每个目录并通过以下命令删除页面
rm *.html*
由于html页面的名称以?=/something
种名称结尾。
所以我决定写一个shell脚本。
但我不清楚的是如何在我的shell脚本中将目录名称作为参数。如果我决定使用for循环或类似的东西。
在这种情况下,我该怎么办?
我不想用
find . -name '*.html*' -exec rm -f {} \;
因为我这样做是为了学习目的。
答案 0 :(得分:2)
此代码段将为当前目录中的每个子目录运行ls
:
for d in * .[!.]* ..?*; do
test -d "${d}" && ls "${d}"
done
您可以调整它以运行您喜欢的每个子目录的命令。
如果您希望深入了解目录层次结构,可以将此代码包装在一个函数中,并为每个子目录重新运行它。
function f {
cd "$1"
# do something in this dir
for d in * .[!.]* ..?*; do
cd "$1"
test -d "$1/$d" && f "$1/$d"
done
}
f "`pwd`"
对于Zsh,您可能想要设置NULL_GLOB选项(-G开关),因此如果没有隐藏的目录,它不会报告错误,在Bash中它默认工作。
答案 1 :(得分:2)
使用bash 4(或zsh),您可以使用globstar“**”来递归匹配。
shopt -s globstar
echo **/*html*
使用如下目录设置:
mkdir -p {a..b}/{c..d}
touch {a..b}/{c..d}/{e..f}.{htmlx,other}
这将导致:
a/c/e.htmlx a/c/f.htmlx a/d/e.htmlx a/d/f.htmlx b/c/e.htmlx b/c/f.htmlx b/d/e.htmlx b/d/f.htmlx
答案 2 :(得分:1)
find
是要走的路。选择错误的方法来解决问题,你将无法学到任何有用的东西。
打印要删除的文件列表
find /your/dir -type f -iname '*.html*'
并删除它们
find /your/dir -type f -iname '*.html*' -delete
find
是一个强大的命令,学会使用它。
改进您不想使用的命令的另一种方法:
find /your/dir -type f -name '*.html*' -exec rm -f {} +
(提示:man find
了解-exec ;
与-exec +
的区别)
请注意,shell脚本只是以最有用的方式使用find
,cat
,ls
,wc
等小型程序。彻底了解这些实用程序是学习shell脚本的必要条件。
答案 3 :(得分:0)
创建一个这样的函数:
myfunc()
{
for dir; do
if [[ -d "$dir" ]]; then
echo rm -rf "${dir}/*.html*"
else
echo "No such dir '$dir'"
fi
done
}
然后通过从
传递要删除 .html 的目录来调用该函数$ myfunc /foo /etc /root
No such dir '/foo'
rm -rf /etc/*.html*
rm -rf /root/*.html*
对输出感到满意后,请移除echo
以使其真正删除文件。
答案 4 :(得分:0)
这基于maarons' answer,但有两个优点:
*/
循环中使用*
代替for
意味着它只会迭代目录而不是所有文件以获得潜在的大加速pushd
和popd
可以轻松支持.
或不支持参数来表示当前目录。这是功能:
g () {
local d bb=/dev/null # bit-bucket
pushd "$1" > $bb
pwd # do something (pwd is a placeholder)
for d in */
do
test -d "$PWD/$d" && g "$PWD/$d" # you could use $(pwd) instead of $PWD
done
popd > $bb
}
当然,将find
与-execdir
一起使用会更简单,并会得到相同的结果。
find -mindepth 1 -type d -execdir sh -c 'cd {}; pwd' \; # (pwd` is a placeholder)