如何在 Unix 和 Windows 换行符格式之间批量转换文件系统分支中的所有文件?

Iva*_*van 15 text-processing newlines

每个人都知道:-) 在 Windows 纯文本文件中,行以 CR+LF 终止,而在 Unix&Linux 中 - 仅以 LF 结尾。如何快速将我的所有源代码文件从一种格式转换为另一种格式?

jan*_*sen 20

这取决于:如果文件受版本控制,这可能是一个相当不受欢迎的历史污染决定。Git 可以选择在签出时自动转换行尾。

如果您不关心并想快速转换,有fromdos/todosdos2unix/ 之类的unix2dos程序可以为您执行此操作。您可以使用findfind . -type f -name '*.php' -exec dos2unix '{}' +


Gil*_*il' 11

有几个专门的程序,包括

只需选择适当方向的工具,然后在命令行上传递要转换的文件名。


如果您没有,但有 Linux 或 Cygwin:

sed -i -e 's/\r\+$//' filename             # dos|unix -> unix
sed -i -e 's/\r*$/\r/' filename            # dos|unix -> dos
Run Code Online (Sandbox Code Playgroud)

如果你有 perl:

perl -i -pe 's/\r+$//' filename            # dos|unix -> unix
perl -i -pe 's/\r*$/\r/' filename          # dos|unix -> dos
Run Code Online (Sandbox Code Playgroud)

仅使用 POSIX 工具(包括 BusyBox),要从 unix 转到 dos,您需要在 sed 命令中逐字传递 CR 字符。

cr=$(echo | tr '\n' '\r')
sed -e "s/$cr*\$/$cr/" <filename >filename.dos
mv filename.dos filename
Run Code Online (Sandbox Code Playgroud)

另一方面,您可以简单地删除所有 CR:

tr -d '\r' <filename >filename.dos
mv filename.dos filename
Run Code Online (Sandbox Code Playgroud)

您可以使用通配符一次转换同一目录中的多个文件,例如

sed -i -e 's/\r\+$//' *.txt
Run Code Online (Sandbox Code Playgroud)

要转换当前目录及其子目录中的所有文件,如果您的shell是zsh,则可以使用**/,例如

sed -i -e 's/\r\+$//' **/*.txt
Run Code Online (Sandbox Code Playgroud)

您可以**/在 bash中使用?4,但您需要先运行shopt -s globstar(您可以将此行放在您的~/.bashrc. 您可以**/在 ksh93中使用,但您需要先运行set -o globstar(您可以将此行放在~/.kshrc.

如果只能使用需要重定向的工具,请使用for循环。

for x in *.txt; do
  tr -d '\r' <"$x" >"$x.dos"
  mv -- "$x.dos" "$x"
done
Run Code Online (Sandbox Code Playgroud)

如果您没有**/或需要更复杂的匹配来选择要转换的文件,请使用该find命令。这是一个 Linux/Cygwin 示例,它递归地转换当前目录及其子目录下的所有文件,除了.o名为bin.

find -name 'bin' -type d -prune -o \
     \! -name '*.o' \
     -exec sed -i -e 's/\r\+$//' {} +
Run Code Online (Sandbox Code Playgroud)

这是一个 POSIX 示例。我们告诉find启动一个可以执行必要重定向的shell。

find -name 'bin' -type d -prune -o \
     \! -name '*.o' \
     -exec sh -c '
       tr -d '\r' <"$0" >"$0.dos"
       mv -- "$0.dos" "$0"
' {} \;
Run Code Online (Sandbox Code Playgroud)

find通过在 shell 命令中使用循环,您可以使该方法稍微快一点,但代价是代码更复杂。

find -name 'bin' -type d -prune -o \
     \! -name '*.o' \
     -exec sh -c '
       for x; do
         tr -d '\r' <"$x" >"$x.dos"
         mv -- "$x.dos" "$x"
       done
' _ {} +
Run Code Online (Sandbox Code Playgroud)