如何在shell脚本中导航到子目录
我有一个目录。这个目录有很多子目录,其中包含html页面和一些c源代码文件、Makefiles等。我试图编写的脚本将从一个包含所有这些子目录的目录中执行。 以下是您可以看到的一组目录和文件如何在shell脚本中导航到子目录,shell,Shell,我有一个目录。这个目录有很多子目录,其中包含html页面和一些c源代码文件、Makefiles等。我试图编写的脚本将从一个包含所有这些子目录的目录中执行。 以下是您可以看到的一组目录和文件 ls delete.sh lddbus Makefile misc-progs sbull scullc scullp short simple snull usb include LICENSE misc-modules pci scull
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脚本。
但我不清楚的是,如果我决定使用for循环或类似的东西,我将如何在shell脚本中将目录名作为参数。
在这种情况下,我应该怎么做?
我不想用
find . -name '*.html*' -exec rm -f {} \;
我这样做是为了学习。此代码段将对当前目录中的每个子目录运行
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中,它默认工作。此代码段将为当前目录中的每个子目录运行
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开关),这样如果没有隐藏的dir,它就不会报告错误,在Bash中,它默认工作。创建如下函数:
myfunc()
{
for dir; do
if [[ -d "$dir" ]]; then
echo rm -rf "${dir}/*.html*"
else
echo "No such dir '$dir'"
fi
done
}
然后通过传递要从中删除.html的目录来调用该函数
输出
一旦您对输出感到满意,请删除echo,让它真正删除文件。创建如下函数:
myfunc()
{
for dir; do
if [[ -d "$dir" ]]; then
echo rm -rf "${dir}/*.html*"
else
echo "No such dir '$dir'"
fi
done
}
然后通过传递要从中删除.html的目录来调用该函数
输出
一旦您对输出感到满意,请删除echo,让它真正删除文件。对于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
对于bash4(或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
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脚本的必要条件。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脚本的必要条件。这是基于以下两个优点:
- 在
循环中使用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)
这是基于,但有两个优点:
- 在
循环中使用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)
最简单的方法:使用递归函数。我不清楚你能举个例子吗?最简单的方法:使用递归函数。我不清楚你能举个例子吗?哇,太棒了。我从来没有遇到过这样的事情。我在想一些非常大的逻辑。您是如何为
ls-1
编写此命令的?您从哪里学来的?解析ls
的输出是一个非常糟糕的主意。阅读以了解原因。这是为了学习,我现在不关心如何解析ls的输出,但感谢这些信息,我会看一看。@Bond:学习好的编程实践永远不会太早用*
替换`ls-1`
,以在极端情况下获得正确的行为。哇,太好了。我从来没有遇到过这样的事情。我在想一些非常大的逻辑。你是如何为ls-1编写这个命令的?你从哪里学来的