Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/15.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
Bash 对目录中的所有文件执行命令_Bash_Scripting - Fatal编程技术网

Bash 对目录中的所有文件执行命令

Bash 对目录中的所有文件执行命令,bash,scripting,Bash,Scripting,是否有人可以提供执行以下操作的代码: 假设有一个文件目录,所有这些文件都需要通过一个程序运行。程序将结果输出到标准输出。我需要一个脚本,它将进入一个目录,对每个文件执行命令,并将输出压缩到一个大的输出文件中 例如,要在1个文件上运行命令: $ cmd [option] [filename] > results.out 这个怎么样: find /some/directory -maxdepth 1 -type f -exec cmd option {} \; > results.ou

是否有人可以提供执行以下操作的代码: 假设有一个文件目录,所有这些文件都需要通过一个程序运行。程序将结果输出到标准输出。我需要一个脚本,它将进入一个目录,对每个文件执行命令,并将输出压缩到一个大的输出文件中

例如,要在1个文件上运行命令:

$ cmd [option] [filename] > results.out
这个怎么样:

find /some/directory -maxdepth 1 -type f -exec cmd option {} \; > results.out
  • -maxdepth 1
    参数防止find递归下降到 任何子目录。(如果希望处理此类嵌套目录,可以忽略此项。)
  • -type-f
    指定只处理普通文件
  • -exec cmd option{}
    告诉它为找到的每个文件使用指定的
    选项运行
    cmd
    ,文件名替换为
    {}
  • \表示命令结束
  • 最后,所有
    cmd
    执行的输出被重定向到
    results.out
但是,如果您关心文件的处理顺序,则 写一个循环可能会更好。我认为
find
会处理这些文件 按inode顺序(尽管我可能错了),这可能不是什么
您需要。

下面的bash代码将$file传递给命令,$file将代表/dir中的每个文件

for file in /dir/*
do
  cmd [option] "$file" >> results.out
done
范例

el@defiant ~/foo $ touch foo.txt bar.txt baz.txt
el@defiant ~/foo $ for i in *.txt; do echo "hello $i"; done
hello bar.txt
hello baz.txt
hello foo.txt

根据@Jim Lewis的方法:

下面是一个快速解决方案,它使用
查找
,并按文件的修改日期对文件进行排序:

$ find  directory/ -maxdepth 1 -type f -print0 | \
  xargs -r0 stat -c "%y %n" | \
  sort | cut -d' ' -f4- | \
  xargs -d "\n" -I{} cmd -op1 {} 
有关排序,请参见:


我在命令行的raspberry pi上运行以下命令:

for i in *;do cmd "$i";done

我需要将所有的.md文件从一个目录复制到另一个目录,所以我做的就是这样。

用于**/*.md中的i;执行mkdir-p../docs/“$i”和&rm-r../docs/“$i”和&cp“$i”“../docs/$i”和&echo“$i->../docs/$i”;完成

这很难读,所以让我们把它分解一下。

将第一张cd与您的文件一起放入目录

用于**/*.md中的i

mkdir-p../docs/“$i”
将该目录置于包含您的文件的文件夹之外的docs文件夹中。这将创建一个与该文件同名的额外文件夹

rm-r../docs/“$i”
删除由于
mkdir-p创建的额外文件夹

cp“$i”“../docs/$i”
复制实际文件

echo“$i->../docs/$i”
echo您所做的


;完成
从此过上幸福的生活

有时完成工作的一种快速而肮脏的方式是:

find directory/ | xargs  Command 
例如,要查找当前目录中所有文件的行数,可以执行以下操作:

find . | xargs wc -l

被接受/投票率高的答案很好,但缺少一些细节。这篇文章介绍了如何更好地处理shell路径名扩展(glob)失败、文件名包含嵌入的换行符/破折号以及将结果写入文件时将命令输出重定向移出for循环的情况

使用
*
运行shell glob扩展时,如果目录中不存在文件,则扩展可能会失败,并且未扩展的glob字符串将传递给要运行的命令,这可能会产生不希望的结果。
bash
shell使用
nullglob
为此提供了一个扩展shell选项。因此,在包含文件的目录中,循环基本上变成如下所示

 shopt -s nullglob

 for file in ./*; do
     cmdToRun [option] -- "$file"
 done
这样,当表达式
/*
不返回任何文件时(如果目录为空),您就可以安全地退出for循环

或者以兼容POSIX的方式(
nullglob
bash
特定的)

这使您可以在表达式失败一次时进入循环,并且条件
[-f“$file”]
检查未展开的字符串
/*
是否为该目录中的有效文件名,而该文件名不可用。因此,在这种情况下,使用
continue
我们恢复到
for
循环,该循环随后不会运行

在传递文件名参数之前,还要注意
--
的用法。这是必需的,因为如前所述,shell文件名可以在文件名的任何位置包含破折号。当名称没有正确引用时,一些shell命令会对此进行解释,并将其视为命令选项,如果提供了标志,则会执行命令

--
发出命令行选项结束的信号,在这种情况下,这意味着命令不应将超出此点的任何字符串解析为命令标志,而应仅解析为文件名


双重引用文件名可以正确地解决名称包含全局字符或空格的情况。但是*nix文件名也可以包含换行符。因此,我们使用唯一不能作为有效文件名一部分的字符(空字节(
\0
)来取消对文件名的限制。由于
bash
在内部使用
C
样式的字符串,其中空字节用于指示字符串的结尾,因此它是正确的候选字符串

因此,使用shell的
printf
选项,使用
read
命令的
-d
选项,用这个空字节分隔文件,我们可以执行以下操作

( shopt -s nullglob; printf '%s\0' ./* ) | while read -rd '' file; do
    cmdToRun [option] -- "$file"
done
nullglob
printf
被包装在
(..)
周围,这意味着它们基本上是在子shell(子shell)中运行的,因为一旦命令退出,为了避免
nullglob
选项反映在父shell上。
read
命令的
-d'
选项与POSIX不兼容,因此需要一个
bash
shell来完成此操作。使用
find
命令,这可以按如下方式完成

while IFS= read -r -d '' file; do
    cmdToRun [option] -- "$file"
done < <(find -maxdepth 1 -type f -print0)

另一个重要的修复方法是将重定向移出for循环,以减少循环中使用的大量文件I/O
while IFS= read -r -d '' file; do
    cmdToRun [option] -- "$file"
done < <(find -maxdepth 1 -type f -print0)
find . -maxdepth 1 -type f -exec printf '%s\0' {} \; | xargs -0 cmdToRun [option] --
( shopt -s nullglob; printf '%s\0' ./* ) | while read -rd '' file; do
    cmdToRun [option] -- "$file"
done > results.out
while IFS= read -r -d '' file; do
    cmdToRun [option] -- "$file"
done < <(find -maxdepth 1 -type f -print0) > results.out
sh /dir/* > ./result.txt
$ export DIR=/path/dir && cd $DIR && chmod -R +x *
$ find . -maxdepth 1 -type f -name '*.sh' -exec {} \; > results.out
$ export DIR=/path/dir && cd $DIR && chmod -R +x *
find . -maxdepth 2 -type f -name '*.sh' | sort | bash > results.out
bash: 1: ./assets/main.sh
bash: 2: ./builder/clean.sh
bash: 3: ./builder/concept/compose.sh
bash: 4: ./builder/concept/market.sh
bash: 5: ./builder/concept/services.sh
bash: 6: ./builder/curl.sh
bash: 7: ./builder/identity.sh
bash: 8: ./concept/compose.sh
bash: 9: ./concept/market.sh
bash: 10: ./concept/services.sh
bash: 11: ./product/compose.sh
bash: 12: ./product/market.sh
bash: 13: ./product/services.sh
bash: 14: ./xferlog.sh
export DIR=/path/dir && cd $DIR && chmod -R +x *
find . -type f -name '*.sh' | sort | bash > results.out
#!/bin/bash
[[ "$(dirname `pwd`)" == $DIR ]] && echo "Executing `realpath $0`.." || return
if <a condition is matched>
then
    #execute child files
    export DIR=`pwd`
fi