通过命令行仅将扩展名附加到目录中的某些文件
Append an extension to only certain files in a directory via command line
我的 QtWidgets 文件夹中有一堆头文件。我遇到的唯一问题是很多文件没有 .cpp
扩展名。我想知道是否有一种方法可以遍历目录并将 .cpp
添加到所有没有 .h
扩展名的文件中?
我已经开始尝试这样的事情了:
paul@pauls-computer:~/QtWidgets$ for f in *; do echo '.cpp'
但这只是开始,它甚至还没有做任何事情。更不用说检查是否附加了 .h
的文件。
所以,我已经标记了一个合适的答案,但似乎有些混乱。我有很多文件,它们要么没有扩展名,要么有 .h
扩展名。没有其他扩展。
假设不应将 .cpp
添加到任何以 .h
或 .cpp
结尾的文件:
mkdir /tmp/test.$$
cd /tmp/test.$$
touch a.h b.cpp c d e.cpp
for f in *
do
[[ "${f}" == *.h || "${f}" == *.cpp ]] && continue
echo mv "${f}" "${f}.cpp"
done
这会生成:
mv c c.cpp
mv d d.cpp
一旦 OP 确认显示了正确的 mv
命令,然后再次删除 echo
和 运行 脚本以执行实际的 mv
。
备注:
- 我强烈建议 OP 在删除
echo
- 如果 OP 更好地定义了哪些文件 NOT 添加
.cpp
(用上述细节更新问题)那么我们可以回头看看在修改提议的代码时
假设 OP 运行 脚本不小心将 .cpp
添加到已有 .cpp
的文件中 ...
mkdir /tmp/test.$$
cd /tmp/test.$$
touch a.h b.cpp c d e.cpp j.cpp.cpp
for f in *.cpp.cpp
do
g="${f/.cpp/}"
echo mv "${f}" "${g}"
done
这会生成:
mv j.cpp.cpp j.cpp
同样,一旦显示的 mv
命令被验证为正确,然后再次删除 echo
和 运行 脚本以执行实际的 mv
' s.
使用 file
命令可以检测类型,而无需仅依赖分机。
> file Pet
Pet: C++ source, ASCII text
> file c-source
c-source: C source, ASCII text
利用这一点我们可以
find
: 文件(不是目录),不以 .h, .cpp
结尾
仅保留匹配 C++ source, C source
的行
仅保留文件名 (cut -d ':' -f1
)
为那些添加 cpp 扩展
while read -r cppfile; do
mv "$cppfile" "${cppfile}.cpp"
done < <(find . -type f -not -name '*.h' -not -name '*.cpp' -exec file {} ';' | grep -E 'C(\+\+)? source' | cut -d ':' -f1)
如果需要遍历子目录,试试find
.
find . -type f \( ! -name '*.cpp' -a ! -name '*.h' \) \
-exec sh -c 'for f; do echo mv "$f" "$f.cpp"; done' _ {} +
您可以根据需要添加更多条件。对结果满意后,取出 echo
。 -type f
选择文件(不是目录、符号链接等),您可能希望限制为 ! -name '*.*'
而不是长括号表达式,以跳过名称中带点的任何文件。
我的 QtWidgets 文件夹中有一堆头文件。我遇到的唯一问题是很多文件没有 .cpp
扩展名。我想知道是否有一种方法可以遍历目录并将 .cpp
添加到所有没有 .h
扩展名的文件中?
我已经开始尝试这样的事情了:
paul@pauls-computer:~/QtWidgets$ for f in *; do echo '.cpp'
但这只是开始,它甚至还没有做任何事情。更不用说检查是否附加了 .h
的文件。
所以,我已经标记了一个合适的答案,但似乎有些混乱。我有很多文件,它们要么没有扩展名,要么有 .h
扩展名。没有其他扩展。
假设不应将 .cpp
添加到任何以 .h
或 .cpp
结尾的文件:
mkdir /tmp/test.$$
cd /tmp/test.$$
touch a.h b.cpp c d e.cpp
for f in *
do
[[ "${f}" == *.h || "${f}" == *.cpp ]] && continue
echo mv "${f}" "${f}.cpp"
done
这会生成:
mv c c.cpp
mv d d.cpp
一旦 OP 确认显示了正确的 mv
命令,然后再次删除 echo
和 运行 脚本以执行实际的 mv
。
备注:
- 我强烈建议 OP 在删除
echo
- 如果 OP 更好地定义了哪些文件 NOT 添加
.cpp
(用上述细节更新问题)那么我们可以回头看看在修改提议的代码时
假设 OP 运行 脚本不小心将 .cpp
添加到已有 .cpp
的文件中 ...
mkdir /tmp/test.$$
cd /tmp/test.$$
touch a.h b.cpp c d e.cpp j.cpp.cpp
for f in *.cpp.cpp
do
g="${f/.cpp/}"
echo mv "${f}" "${g}"
done
这会生成:
mv j.cpp.cpp j.cpp
同样,一旦显示的 mv
命令被验证为正确,然后再次删除 echo
和 运行 脚本以执行实际的 mv
' s.
使用 file
命令可以检测类型,而无需仅依赖分机。
> file Pet
Pet: C++ source, ASCII text
> file c-source
c-source: C source, ASCII text
利用这一点我们可以
结尾find
: 文件(不是目录),不以.h, .cpp
仅保留匹配
C++ source, C source
的行仅保留文件名 (
cut -d ':' -f1
)为那些添加 cpp 扩展
while read -r cppfile; do mv "$cppfile" "${cppfile}.cpp" done < <(find . -type f -not -name '*.h' -not -name '*.cpp' -exec file {} ';' | grep -E 'C(\+\+)? source' | cut -d ':' -f1)
如果需要遍历子目录,试试find
.
find . -type f \( ! -name '*.cpp' -a ! -name '*.h' \) \
-exec sh -c 'for f; do echo mv "$f" "$f.cpp"; done' _ {} +
您可以根据需要添加更多条件。对结果满意后,取出 echo
。 -type f
选择文件(不是目录、符号链接等),您可能希望限制为 ! -name '*.*'
而不是长括号表达式,以跳过名称中带点的任何文件。