Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在shell脚本中导航到子目录_Shell - Fatal编程技术网

如何在shell脚本中导航到子目录

如何在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

我有一个目录。这个目录有很多子目录,其中包含html页面和一些c源代码文件、Makefiles等。我试图编写的脚本将从一个包含所有这些子目录的目录中执行。 以下是您可以看到的一组目录和文件

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编写这个命令的?你从哪里学来的