我在 OS X 上,我有一个包含多个子文件夹的文件夹。我想做两件事。第一是确保每个子文件夹中都有一个格式为 [子文件夹名称].grade.xml 的文件,然后我需要在相应的文件中搜索和替换以进行一些更改。
对于第二部分,我知道如何使用 sed 对单个文件执行我需要的操作,但我遇到了验证文件是否存在,然后在其上运行命令的问题。任何有关此操作的提示都将不胜感激。
注意:我并不一定需要完整的答案,尤其是因为我正在尝试在这里学习。不过,一个指向正确方向的指针会很好。
(我意识到可能有比命令行更好的方法来实现这一点,但是我需要并且将来需要在其他基于 Unix 的系统上做类似的事情,所以我宁愿知道:)
答案1
#!/bin/bash
# Get directory name from argument, default is .
DIR=${1:-.}
# For each subfolder in DIR (maxdepth limits to one level in depth)
find "${DIR}" -maxdepth 1 -type d | while read dir; do
# Check that there is a file called $dir.grade.xml in this dir
dirname=$(basename "${dir}")
gradefile="${dirname}"/"${dirname}".grade.xml
if [ -e "${gradefile}" ]; then
sed -i .bak "s/foo/bar/g" "${gradefile}"
else
echo "Warning: ${dir} does not contain ${gradefile}"
fi done
对 Raphink 框架进行细微调整。
关键点:
- 直接检查文件是否存在,
[ -e filename ]
而不是运行 ls - 把所有变量放进去
${variablename}
;通常不是严格必要的,但可以避免歧义(${variablename}
并且${variable}name
显然不同,$variablename
可能意味着任何一种) - 将扩展名传递给 sed 以创建备份文件。这既是好的做法(以防您的处理出错),也是 OSX 上的强制性要求(raphink 的版本将其解释
s/foo/bar/g
为您想要的备份文件扩展名,然后尝试将文件名解析为命令)。 - 好吧,我撒谎了,不是实际上强制性的 - 您可以用来
sed -i "" "s/foo/bar/g" ${gradefile}
传递一个空的扩展,这将导致 sed 不进行备份。
答案2
好的,你需要为此编写一个脚本。我将选择 bash。
#!/bin/bash
# Get directory name from argument, default is .
DIR=${1:-.}
# For each subfolder in DIR (maxdepth limits to one level in depth)
find $DIR -maxdepth 1 -type d | while read dir; do
# Check that there is a file called *.xml in this dir
if ls $dir/*.xml &>/dev/null; then
# Loop through xml files found in $dir
# or do you actually need to check that there is only ONE file?
for xmlfile in $dir/*xml; do
# Do whatever treatment with sed you wish to do
sed -i 's/foo/bar/g' $xmlfile
done
else
echo "Warning: $dir does not have a *xml file in it"
fi
done
将该文件保存为 .sh 脚本,然后运行
$ chown +x yourscript.sh
$ ./yourscript.sh /path/to/dir # Path is optional, defaults to .