通过命令行仅将扩展名附加到目录中的某些文件

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 '*.*' 而不是长括号表达式,以跳过名称中带点的任何文件。