递归地循环bash中的文件,并通过命令操作每个文件

递归地循环bash中的文件,并通过命令操作每个文件,bash,unix,command-line-interface,file-manipulation,Bash,Unix,Command Line Interface,File Manipulation,我希望递归地遍历bash文件夹中的每个文件,并对它们进行某种简单的操作。例如,更改权限、更改时间戳、使用ImageMagick调整图像大小等,您就知道了 像大多数初学者一样,我知道如何在目录中执行它,但是递归地 $ for f in *.jpg ; do convert $f -scale 25% resized/$f ; done 让我们保持简单。说 $ for f in *; do touch $f; done 使用globstar: 从: 环球之星 如果设置,文件名扩展上下文中使用的模

我希望递归地遍历bash文件夹中的每个文件,并对它们进行某种简单的操作。例如,更改权限、更改时间戳、使用ImageMagick调整图像大小等,您就知道了

像大多数初学者一样,我知道如何在目录中执行它,但是递归地

$ for f in *.jpg ; do convert $f -scale 25% resized/$f ; done
让我们保持简单。说

$ for f in *; do touch $f; done
使用globstar:

从:

环球之星

如果设置,文件名扩展上下文中使用的模式“**”将匹配所有文件以及零个或多个目录和子目录。如果模式后跟“/”,则只有目录和子目录匹配

顺便说一句,还有

这是基于的答案

使用globstar:

从:

环球之星

如果设置,文件名扩展上下文中使用的模式“**”将匹配所有文件以及零个或多个目录和子目录。如果模式后跟“/”,则只有目录和子目录匹配

顺便说一句,还有


这是基于的答案,当你说bash时,你真的是指在bash中还是仅仅使用常用的命令行工具编写脚本

一起编写脚本工具 这意味着对于当前目录中的每个文件,都要使其可执行。这个\;正在通过考试;到find命令,该命令将其解释为分别调用每个找到的路径上的exec字符串。您可以替换\;使用\+命令find首先收集所有路径并将其替换为{}所有路径。通常\+会更有效,但您必须小心使用命令行长度,因为这是有限制的。然后,您可以将其与xargs结合使用:

find . -type f -print0 | xargs -0 -P $(nproc) -I{} chmod u+x {}
它告诉find使用空字符作为终止符,而不是换行符。这样可以确保即使每个条目包含任意空格或随机UTF字符,\0不是路径的有效部分,也能正确处理该条目。xargs的-0选项告诉它在读取参数而不是newlien时使用\0作为分隔符。P选项表示并行运行命令N次,在本例中,N是打印处理器数量的nproc命令的输出-I是替换字符串,其余是要处理的命令字符串

find&xargs的手册页非常适合探索

在Bash中固有地 很可能您正在寻找一个完全在Bash中的解决方案&没有外部工具,它有点复杂&将涉及一些更高级的Bash特定语言构造,您可以在其中实现find-your。要迭代目录的内容,您需要执行类似于中的路径的操作;做然后,您将使用测试内置[[-d$path]]来确定它是否是一个目录,[-f$path]]如果它是一个文件,等等。man测试有很多解释,但请注意,这是一个独立的测试可执行文件,它与功能更丰富、更安全的bash版本[[]]有细微的区别和缺陷

使用bash阵列: Bash测试简介:

测试介绍中没有提到的是正则表达式之类的东西,它将成为该语法的一部分。Bash还提供了操作变量内容的强大选项:

但是在实践中,无论是在bash中还是通过组合工具,任何稍微复杂的东西都可能得到更好的维护&以拥有大量bash经验的人的身份来说,用Python阅读都更容易

find_files() {
  if [[ ! -x "$1" ]]; then
     echo "$1 isn't a directory" >&2
     return 1
  fi

  local dirs=("$1")

  while [[ "${#dirs[@]}" -gt 0 ]]; do
    local dir="${dirs[0]}"
    dirs=("${dirs[@]:1}") # pop the element from above

    # whitespace in filenames iterated will be a problem. Look to the IFS
    # variable to handle those more gracefully.
    for p in "${dir}"/*; do 
      if [[ -d "$p" ]]; then
         dirs+=("$p")
      elif [[ -f "$p" ]]; then
         echo "$p"
      fi
    done
  done
}

for f in $(find_files .); do
    chmod u+x "$f"
done

正如您所见,这比仅仅使用find/xargs二进制文件更复杂、更复杂、更慢。你永远不会想在现实中写那样的东西。您甚至可以在将find_文件转换为进程的过程中使用一个命令,然后在迭代时对该命令求值,而不是通过eval回送路径。eval非常棘手&可能是一种安全漏洞。

当你说bash时,你真的是指在bash中还是仅仅使用常用的命令行工具编写脚本

一起编写脚本工具 这意味着对于当前目录中的每个文件,都要使其可执行。这个\;正在通过考试;到find命令,该命令将其解释为分别调用每个找到的路径上的exec字符串。您可以替换\;使用\+命令find首先收集所有路径并将其替换为{}所有路径。通常\+会更有效,但您必须小心使用命令行长度,因为这是有限制的。然后,您可以将其与xargs结合使用:

find . -type f -print0 | xargs -0 -P $(nproc) -I{} chmod u+x {}
它告诉find使用空字符作为终止符,而不是换行符。这样可以确保即使每个条目包含任意空格或随机UTF字符,\0不是路径的有效部分,也能正确处理该条目。xargs的-0选项告诉它在读取参数而不是newlien时使用\0作为分隔符。P选项表示并行运行命令N次,在本例中,N是打印处理器数量的nproc命令的输出-I是替换字符串和 rest是要处理的命令字符串

find&xargs的手册页非常适合探索

在Bash中固有地 很可能您正在寻找一个完全在Bash中的解决方案&没有外部工具,它有点复杂&将涉及一些更高级的Bash特定语言构造,您可以在其中实现find-your。要迭代目录的内容,您需要执行类似于中的路径的操作;做然后,您将使用测试内置[[-d$path]]来确定它是否是一个目录,[-f$path]]如果它是一个文件,等等。man测试有很多解释,但请注意,这是一个独立的测试可执行文件,它与功能更丰富、更安全的bash版本[[]]有细微的区别和缺陷

使用bash阵列: Bash测试简介:

测试介绍中没有提到的是正则表达式之类的东西,它将成为该语法的一部分。Bash还提供了操作变量内容的强大选项:

但是在实践中,无论是在bash中还是通过组合工具,任何稍微复杂的东西都可能得到更好的维护&以拥有大量bash经验的人的身份来说,用Python阅读都更容易

find_files() {
  if [[ ! -x "$1" ]]; then
     echo "$1 isn't a directory" >&2
     return 1
  fi

  local dirs=("$1")

  while [[ "${#dirs[@]}" -gt 0 ]]; do
    local dir="${dirs[0]}"
    dirs=("${dirs[@]:1}") # pop the element from above

    # whitespace in filenames iterated will be a problem. Look to the IFS
    # variable to handle those more gracefully.
    for p in "${dir}"/*; do 
      if [[ -d "$p" ]]; then
         dirs+=("$p")
      elif [[ -f "$p" ]]; then
         echo "$p"
      fi
    done
  done
}

for f in $(find_files .); do
    chmod u+x "$f"
done

正如您所见,这比仅仅使用find/xargs二进制文件更复杂、更复杂、更慢。你永远不会想在现实中写那样的东西。您甚至可以在将find_文件转换为进程的过程中使用一个命令,然后在迭代时对该命令求值,而不是通过eval回送路径。eval非常棘手,可能是一种安全漏洞。

那么,展示一下你目前的情况。-而且,作业通常不仅仅是一个问题。我们不知道您需要什么帮助,所以请具体说明。*.jpg中f的$;不转换$f-缩放25%大小/f;done@GaurangiS-您的循环不是递归的。最简单的解决方案是编写一个简短的脚本,将单个文件名作为参数,并对其执行所有需要的操作。调用是说fixfiles并使其可执行chmod+xfixfiles。现在只需使用find和-exec选项,并对每个文件调用fixfiles脚本,例如,使用$HOME中的fixfiles,就可以进行查找-类型f-exec$HOME/fixfiles'{}\;对当前目录及以下目录中的每个文件进行操作,并对其应用修复文件。将fixfiles视为findBy递归调用的助手脚本,您的意思是希望它也能在子目录中查找文件吗?类似的问题:,那么,展示一下您到目前为止得到了什么。-而且,作业通常不仅仅是一个问题。我们不知道您需要什么帮助,所以请具体说明。*.jpg中f的$;不转换$f-缩放25%大小/f;done@GaurangiS-您的循环不是递归的。最简单的解决方案是编写一个简短的脚本,将单个文件名作为参数,并对其执行所有需要的操作。调用是说fixfiles并使其可执行chmod+xfixfiles。现在只需使用find和-exec选项,并对每个文件调用fixfiles脚本,例如,使用$HOME中的fixfiles,就可以进行查找-类型f-exec$HOME/fixfiles'{}\;对当前目录及以下目录中的每个文件进行操作,并对其应用修复文件。将fixfiles视为findBy递归调用的助手脚本,您的意思是希望它也能在子目录中查找文件吗?类似的问题:,哦,太好了。我不知道环球之星。但有一件事需要注意,我认为你最终也会处理目录。@Vitali-True。您可以添加一个简单的检查来跳过dirs:[[-d$f]]&&continueOh-neat。我不知道环球之星。但有一件事需要注意,我认为你最终也会处理目录。@Vitali-True。您可以添加一个简单的检查来跳过dirs:[[-d$f]]&&continue