我想将具有以下扩展名的文件重命名:.txt、.data、.conf 至“.xml”
你好.txt -> 你好.xml
为此,文件还必须包含以下行:<?xml version="1.0" encoding="UTF-8"?>
这就是我所拥有的:
for file in *
do
if [ $(grep -Rc '<?xml version="1.0" encoding="UTF-8"?>' --include ".txt" --include ".data" --include "*.conf") = true ]
then
rename extension to: .xml
fi
done
有任何想法吗?
答案1
如果你需要这样做grep
然后for
也许是这样的?
grep -RlZ '<?xml version="1.0" encoding="UTF-8"?>' --include "*.txt" --include "*.data" --include "*.conf" |
xargs -0 sh -c 'for f; do echo mv -- "$f" "${f%.*}.xml"; done' sh
(echo
一旦您确信它正在做正确的事情,请删除)。
grep -RlZ
输出找到匹配项的文件名称的空分隔列表xargs -0
将该空分隔列表传递给sh -c
for f
将文件名作为位置参数循环
或者(如果允许您使用while
而不是for
)您可以跳过xargs
和附加的 shell scriptlet,例如
grep -RlZ '<?xml version="1.0" encoding="UTF-8"?>' --include "*.txt" --include "*.data" --include "*.conf" |
while IFS= read -r -d '' f; do echo mv -- "$f" "${f%.*}.xml"; done
答案2
find . -type f \( -name "*.txt" -o -name "*.data" -o -name "*.conf" \) -exec sh -c '
for file in "$@"; do
if grep -qF "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" "$file"; then
mv -- "$file" "${file%.*}.xml"
fi
done
' findshell {} +
我认为find
在这种情况下更合适。它递归地查找带有.txt
,.data
和.conf
扩展名的常规文件,并检查您提供的字符串是否存在于每个文件中。如果是,那么它将.xml
通过命令将扩展名更改为mv
。
如果您不确定代码是否会按预期工作,您可以在echo
前面添加一个mv
以查看它的作用。
我还应该提到该脚本不依赖于非 POSIX 实用程序。
答案3
你可以试试这个:
for file in *.{txt,conf}; do
[[ $(grep "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" "$file") ]] && \
mv "$file" "${file%.*}.xml" || echo "$file" " does not match"
done
答案4
使用bash
:
shopt -s globstar dotglob nullglob extglob
string='<?xml version="1.0" encoding="UTF-8"?>'
for pathname in ./**/*.@(txt|data|conf); do
if [[ -f $pathname ]] && grep -q -F "$string" "$pathname"; then
mv -i "$pathname" "${pathname%.*}.xml"
fi
done
我首先设置一些默认情况下通常不会设置的 shell 选项bash
:
globstar
启用**
递归匹配子目录的通配模式。dotglob
使通配模式与隐藏名称相匹配。nullglob
使不匹配的模式完全消失,而不是保持未展开状态。这确保了如果没有匹配,我们的循环稍后将不会运行。extglob
启用扩展的通配模式,例如@(txt|data|conf)
匹配括号内的字符串之一。
然后,我们循环遍历候选名称并测试每个名称的给定字符串。如果找到该字符串,则通过将最后一个点字符后面的文件名后缀替换为 来重命名该文件xml
。