如何在整个目录上运行dos2unix?

433

我需要使用dos2unix将整个目录转换格式。但是我无法弄清楚如何操作。


3
这是a meta question的主题。 - Peter Mortensen
11个回答

795

find . -type f -print0 | xargs -0 dos2unix

这行命令将递归查找当前目录下的所有文件,并为这些文件调用dos2unix命令。


1
我输入了以下命令:find . -type f -exec dos2unix {} /home/venuk/Desktop/NEO_Src,但是它报错了,提示“find: missing argument to `-exec'”。 - Vivek Gaur
2
请注意反斜杠转义分号,以确保dos2unix命令由分号分隔,以免它们被混在一起。如果您想在之后运行另一个命令,则需要另一个分号,因此\;; echo Hello - Josh
5
@vguzmanp 回复道,find 命令并不会进行这项检查(虽然添加此功能很简单),但现代的 dos2unix 命令会正确跳过二进制文件。 - Kyle Strand
3
警告:如果你在一个包含 .git 索引的目录中运行这个命令,你的 git 索引将被损坏。 - mbomb007
9
为了避免 .git 索引损坏并保留 UTF-8 BOM,我最终使用了 find . -type f -print0 | xargs -0 dos2unix -ic0 | xargs -0 dos2unix -b 命令。该命令仅对包含 Windows 换行符的文件进行操作(得益于 -ic0 过滤选项),忽略所有其他文件。如果您的存储库包含带有 UTF-8 BOM 的文件,则 -b 选项也很有用,它可以保留 BOM。 - Konard
显示剩余13条评论

95
如果是一个大目录,您可能需要考虑使用多个处理器运行:
find . -type f -print0 | xargs -0 -n 1 -P 4 dos2unix 

这将逐个处理1个文件,并使用4个处理器。


1
这种方法的优点是,即使dos2unix遇到任何问题,它也可以继续执行!就像“--force”方法一样。谢谢你! - freeo
6
为每个文件启动一个新的dos2unix进程会引入极其不必要的开销。我建议将“n”增加一个数量级或两个数量级(取决于这里有多少个文件)。 - JonoCoetzee
1
很棒的回答!@JonoCoetzee,这里我使用了-n 50 - Gabriel Staples

30

因为我对dos2unix不太满意,所以我自己开发了一个简单的实用程序。除了速度和可预测性方面有一些优势之外,语法也更加简单:

endlines unix *

如果您希望其进入子目录(跳过隐藏目录和非文本文件):

endlines unix -r .

endlines 可在此处获取:https://github.com/mdolidon/endlines


1
这太完美了!我能找到的最接近的一行代码是在这里:https://unix.stackexchange.com/a/365679/112190 - phyatt
4
它怎样比“dos2unix”更好?我真的很好奇。 - Walf
3
1/ 主要有很多不同的 dos2unix,具有不同的功能(例如一些可以读取UTF32,而另一些则不能;换行符也不同)。只有一个 endlines,其功能是众所周知的。 2/ 对输入宽容,但并非所有的 dos2unix 都是如此。 3/ 高效的文件树探索,旨在快速实用地处理数以万计的文件。 4/ 可在OSX上直接运行 - 尽管现在有Brew软件包存在这个功能已经不那么重要了。 - Mathias Dolidon

29

一个常见的用例似乎是为所有提交到 Git 存储库的文件 标准化行尾

git ls-files -z | xargs -0 dos2unix

请注意,某些文件(例如*.sln*.bat)仅适用于Windows操作系统,并应保留CRLF结尾:

git ls-files -z '*.sln' '*.bat' | xargs -0 unix2dos

如有必要,请使用.gitattributes


1
我已经为你的回答点赞了,但是有一件事情需要解决:它在路径中包含空格的文件上失败了,因为 xargs 默认将所有空格作为分隔符。xargs 手册显示了一个 --delimiter 选项,但建议在输入可能包含空格时使用 --null 选项。我没有测试过这个选项,但是在你的命令中添加 --null 会产生以下结果: git ls-files | xargs --null dos2unix - Pulseczar
1
谢谢@Pulseczar - 是的,你是正确的,如果文件名包含空格,该命令将失败。你的评论帮助我找到了答案(它还需要-z用于ls-files)。我已经更新了我的答案。再次感谢! - friederbluemle

24

最好跳过隐藏文件和文件夹,例如.git.,因此,如果您使用的是足够新的bash版本或者您正在使用zsh,那么只需执行以下操作:

dos2unix **

请注意,对于Bash来说,这将需要:

shopt -s globstar

......但这个功能非常有用,你应该将其放入你的.bashrc中。

如果你不想跳过隐藏文件和文件夹,但你仍然不想折腾find(我也不怪你),你可以提供第二个递归通配符参数来匹配只有隐藏项:

dos2unix ** **/.*

请注意,在这两种情况下,通配符将会扩展以包括目录,因此您可能会看到以下警告(可能会重复多次):Skipping <dir>, not a regular file.


1
这对我没用。globstar语法适用于dos2unix吗?我在其他地方成功使用了globstar,但无法使其工作。我正在使用Bash 4.3.11(1)。 - dutoitns
1
@NSduToit 这里有些混淆。我的回答明确指出使用 ** 而不是 find目的是“跳过隐藏文件和文件夹,例如 .git”。因为 ** 不会展开显示隐藏文件,所以 dos2unix 永远不会看到这些隐藏文件。如果你想要自动运行 dos2unix 来处理隐藏文件和文件夹,你可以使用 find 或者 dos2unix ** **/.***/.* 将只展开当前文件夹中的隐藏文件和文件夹,包括 .(根目录)、..(父目录)以及任何其他隐藏条目。 - Kyle Strand
type dos2unix returns dos2unix is hashed (/usr/bin/dos2unix) - dutoitns
1
(请注意,仅在文件夹上运行dos2unix时会打印Skipping <dir>, not a regular file.,因此在...上运行是安全的。)此外,将ls与glob组合使用不是检查glob扩展方式的好方法;改用echoecho **将打印dos2unix **dos2unix接收到的参数。 - Kyle Strand
1
谢谢!很有道理!好的,我对**的含义完全误解了,使用echo让它变得清晰明了。 - dutoitns
显示剩余5条评论

7

我已经像搜索一百万次了,所以我的解决方案就是将这个bash函数放到您的环境中。

.bashrc 或者 .profile 或任何其他文件

dos2unixd() {
  find $1 -type f -print0 | xargs -0 dos2unix
}

用法

$ dos2unixd ./somepath

这样你仍然有原始命令dos2unix,并且很容易记住这个命令dos2unixd


7

对于任何Solaris用户(我正在使用5.10,新版本以及其他Unix系统可能也适用):

dos2unix不会默认覆盖文件,它只会将更新后的版本打印到标准输出,因此您需要指定源和目标,即两次使用相同的名称:

find . -type f -exec dos2unix {} {} \;

6
我认为最简单的方法是:
dos2unix $(find . -type f)

4

我曾经遇到过同样的问题,感谢这里的帖子,我已经解决了。我知道我有大约一百个文件,我只需要运行*.js文件。

find . -type f -name '*.js' -print0 | xargs -0 dos2unix

感谢大家的帮助。


2
for FILE in /var/www/html/files/*
do
 /usr/bin/dos2unix FILE
done

2
欢迎来到Stack Overflow。虽然您的解决方案是有效的,但如果您能添加一些解释就更好了。您可能还考虑引用其他答案来证明您的答案。请查看[answer]以获取更多信息。 - kvantour

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接