Bash 对目录中的所有文件执行命令
是否有人可以提供执行以下操作的代码: 假设有一个文件目录,所有这些文件都需要通过一个程序运行。程序将结果输出到标准输出。我需要一个脚本,它将进入一个目录,对每个文件执行命令,并将输出压缩到一个大的输出文件中 例如,要在1个文件上运行命令:Bash 对目录中的所有文件执行命令,bash,scripting,Bash,Scripting,是否有人可以提供执行以下操作的代码: 假设有一个文件目录,所有这些文件都需要通过一个程序运行。程序将结果输出到标准输出。我需要一个脚本,它将进入一个目录,对每个文件执行命令,并将输出压缩到一个大的输出文件中 例如,要在1个文件上运行命令: $ cmd [option] [filename] > results.out 这个怎么样: find /some/directory -maxdepth 1 -type f -exec cmd option {} \; > results.ou
$ cmd [option] [filename] > results.out
这个怎么样:
find /some/directory -maxdepth 1 -type f -exec cmd option {} \; > results.out
参数防止find递归下降到 任何子目录。(如果希望处理此类嵌套目录,可以忽略此项。)-maxdepth 1
指定只处理普通文件-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