如何递归地将dos2unix应用到文件夹的所有内容?

如何递归地将dos2unix应用到文件夹的所有内容?

有没有办法应用该dos2unix命令,以便它针对文件夹及其子文件夹中的所有文件运行? man dos2unix没有显示任何-r或类似的选项可以让这一切变得简单?

答案1

find /path -type f -print0 | xargs -0 dos2unix --

答案2

使用bash

shopt -s globstar
dos2unix **

shellglobstar选项bash允许使用 glob **。这与路径名类似*,但匹配/路径名(因此也匹配子目录中的名称)。这适用于子目录中包含适量文件(不是数千个)的目录。

zsh在和shell中yash(使用set -o extended-globin yash),你会做

dos2unix **/*

答案3

跳过二进制文件和隐藏文件对我来说很重要:

这对我来说效果很好:

find . -type f -not -path '*/\.*' -exec grep -Il '.' {} \; | xargs -d '\n' -L 1 dos2unix -k

这意味着:在当前目录中递归查找所有非隐藏文件,然后使用 grep 列出所有非二进制 (-I) 非空文件,然后将其通过管道传输到 xargs(由换行符分隔),一次一个文件dos2unix 并保留原始时间戳。

也可以看看:

https://github.com/mdolidon/endlines

答案4

如何dos2unix使用多个进程在所需的目录或路径上递归运行(或任何其他命令)

这个答案也隐含地涵盖了“如何使用xargs”。

我结合了最好的这个答案,这个答案, 和这个答案,做出我自己的答案,根据您的需要有 3 个单独的解决方案:

  1. 运行dos2unix(或任何其他命令)整个目录中的所有文件。

    find . -type f -print0 | xargs -0 -n 50 -P $(nproc) dos2unix
    

    (注意:做不是在 git 存储库中运行上述命令,否则它会破坏目录中的某些内容.git,并使您必须从头开始重新克隆目录!对于 git 目录,您必须排除.gitdir。请参阅下面的解决方案。)

  2. 运行dos2unix(或任何其他命令)整个 git 存储库中的所有文件或所有签入的文件:

    # A) Use `git ls-files` to find just the files *checked-in* to the repo.
    git ls-files -z | xargs -0 -n 50 -P $(nproc) dos2unix
    
    # Or B): use `find`, to find all files in this dir, period, but exclude the
    # `.git` dir so we don't damage the repo. 
    # - See my answer on excluding directories using `find`:
    #   https://stackoverflow.com/a/69830768/4561887
    find . -not \( -path "./.git" -type d -prune \) -type f -print0 \
        | xargs -0 -n 50 -P $(nproc) dos2unix
    
  3. 运行dos2unix(或任何其他命令)git 存储库中指定目录或多个目录中的所有文件或所有签入的文件:

    # 1. only in this one directory: "path/to/dir1":
    
    # A) Use `git ls-files` to find just the files checked-in to the repo.
    git ls-files -z -- path/to/dir1 | xargs -0 -n 50 -P $(nproc) dos2unix
    
    # Or B): use `find` to find all files in this repo dir, period.
    find path/to/dir1 -type f -print0 | xargs -0 -n 50 -P $(nproc) dos2unix
    
    
    # 2. in all 3 of these directories:
    
    # A) Use `git ls-files` to find just the files checked-in to the repo.
    git ls-files -z -- path/to/dir1 path/to/dir2 path/to/dir3 \
        | xargs -0 -n 50 -P $(nproc) dos2unix
    
    # Or B): use `find` to find all files in these 3 repo dirs, period. Note
    # that by specifying specific folders you are automatically excluding the
    # `.git` dir, which is what you need to do.
    find path/to/dir1 path/to/dir2 path/to/dir3 -type f -print0 \
        | xargs -0 -n 50 -P $(nproc) dos2unix
    

速度:

不幸的是,我没有写下运行它所花费的时间,但我知道git ls-files -z | xargs -0 -n 50 -P $(nproc) dos2unix上面的命令转换了大约我的庞大 git 存储库中有 150 万个文件在 < 3 分钟内。我上面使用的多进程命令有帮助一吨,使我的计算机的总 CPU 处理能力(由 20 个内核组成)在整个过程期间总体利用率高达 90%。

解释:

  1. dos2unix是我们通过 运行的命令xargs
  2. in 、-print0in和in均表示“零分隔”或“空分隔”文件路径列表。这样,只需查找分隔它们的二进制零,即可轻松分隔具有特殊字符和空格的文件路径。find-0xargs-zgit ls-files
  3. nproc列出您的计算机拥有的 CPU 核心数(例如:8)。因此,传递-P $(nproc)表示生成与我们拥有的核心一样多的进程来运行命令(dos2unix在我们的例子中)。这样,我们尝试通过为每个 CPU 核心生成一个工作进程来优化运行时。
  4. xargs允许从流中通过管道传输到它的输入运行单独的命令。
  5. -n 50说通过50 个文件路径生成运行命令的每个进程(dos2unix在我们的例子中);这样,我们减少了生成新进程的开销,dos2unix因为我们一次传递多个文件来处理,而不是仅仅传递一个或两个或几个文件。
  6. find .-type f在当前目录 ( ) 中查找文件 ( ) .
  7. git ls-files列出 git 存储库中的所有文件。
    1. --git ls-files通过向其解析器标记此后不会再有此函数的选项来结束传递给的选项。通过这种方式,它知道后面的所有内容--都将是文件或文件夹路径的列表。

参考:

  1. 我上面链接到的 3 个答案。
  2. 我从哪里了解到nproc如何从命令行获取Linux中的CPU/核心数?
  3. 我的回答是使用时如何排除目录find

也可以看看:

  1. 如何找出文本文件中的行结尾?-如果您只想查看行结尾,请在上面的命令中使用file而不是dos2unix目前是对于给定目录中的所有文件。
  2. 我的答案:Git 中的文件限制是多少(数量和大小)?
  3. GitHub:配置 Git 处理行结尾
  4. 我的另一个xargs例子,添加了-I{}指定参数放置的选项:如何使用并行操作(每个进程一个 CPU 核心,有多少个核心就有多少个进程)一次解压缩多个文件到与 zip 文件同名的输出目录中
  5. 有时您需要使用bash -cwithxargs才能获得正确的替换,例如 with dirname。看这里:Stack Overflow:为什么在 find 命令中使用 dirname 会为每个匹配项提供点?
    1. 我在一些xargs命令中使用了这个技巧来提取我的存储库中的 .zip 文件:https://github.com/ElectricRCAaircraftGuy/FatFs。请参阅这些命令的自述文件xargs

相关内容