Is there a way to apply the dos2unix
command so that it runs against all of the files in a folder and it's subfolders?
man dos2unix
doesn't show any -r
or similar options that would make this straight forward?

- 22,765

- 525
-
See also: Stack Overflow: How can I run dos2unix on an entire directory? – Gabriel Staples Jul 19 '23 at 18:08
6 Answers
find /path -type f -print0 | xargs -0 dos2unix --

- 785
-
11
-
Better said,
dos2unix
tries to skip binaries (by default). I wouldn't trust that it always succeeds. I'd feel much safer running a separate command for each file extension, as suggested in this answer. – Henke - Нава́льный П с м Mar 06 '23 at 12:54
Using bash
:
shopt -s globstar
dos2unix **
The globstar
shell option in bash
enables the use of the **
glob. This works just like *
but matches across /
in pathnames (hence matching names in subdirectories too). This would work in a directory containing a moderate number of files in its subdirectories (not many thousands).
In the zsh
and yash
shells (with set -o extended-glob
in yash
), you would do
dos2unix **/*

- 333,661
Skipping binaries and hidden files were important for me:
This one worked well for me:
find . -type f -not -path '*/\.*' -exec grep -Il '.' {} \; | xargs -d '\n' -L 1 dos2unix -k
Which translates to: find all non-hidden files recursively in the current directory, then using grep, list all non-binary (-I) non-empty files, then pipe it into xargs (delimited by newlines) one file at a time to dos2unix and keep the original timestamp.
See also:

- 56,709
- 26
- 150
- 232

- 607
You can use find to find all of the files in a directory structure that you want to run through your dos2unix command
find /path/to/the/files -type f -exec dos2unix {} \;
Take a look at the man pages for find, there are a lot of options that you can use to specify what gets evaluated

- 160
-
-
3Be VERY carefull running this if there is a .git directory anywhere down the file tree...it corrupted my local git repository. – Aaron_H Jul 20 '17 at 18:59
How to recursively run dos2unix
(or any other command) on your desired directory or path using multiple processes
This answer also implicitly covers "how to use xargs
".
I've combined the best from this answer, this answer, and this answer, to make my own answer, with 3 separate solutions depending on what you need:
Run
dos2unix
(or any other command) on all files in an entire directory.find . -type f -print0 | xargs -0 -n 50 -P $(nproc) dos2unix
(NB: do not run the above command in a git repository or else it will botch some of the contents of your
.git
dir and make you have to re-clone the directory from scratch! For git directories, you must exclude the.git
dir. See the solutions below for that.)Run
dos2unix
(or any other command) on all files, or all checked-in files, in an entire git repository:# 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) dos2unixRun
dos2unix
(or any other command) on all files, or all checked-in files, in a specified directory or directories within a git repository:# 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) dos2unixOr B): use
find
to find all files in these 3 repo dirs, period. Notethat 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
Speed:
Unfortunately, I didn't write down the time it took when I ran it, but I know that the git ls-files -z | xargs -0 -n 50 -P $(nproc) dos2unix
command above converted about 1.5M files in my massive git repo in < 3 minutes. The multi-process command I used above helped a ton, allowing my computer's total CPU processing power (consisting of 20 cores) to be as high as 90% utilized overall throughout the duration of the procedure.
Explanation:
dos2unix
is the command we are running viaxargs
.- The
-print0
infind
,-0
inxargs
, and-z
ingit ls-files
, all mean to "zero-separate", or "null-separate" file path listings. This way, file paths with special chars and spaces are easily separated by simply looking for the binary zero separating them. nproc
lists the number of CPU cores your computer has (ex: 8). So, passing-P $(nproc)
says to spawn as many processes to run the command (dos2unix
in our case) as we have cores. This way, we attempt to optimize the run-time by spawning one worker process per CPU core.xargs
allows running individual commands from input piped to it in a stream.-n 50
says to pass 50 filepaths to each process spawned to run the command (dos2unix
in our case); this way, we reduce the overhead of spawning a newdos2unix
process since we pass it many files at once to process, rather than just one or two or a few.find .
finds files (-type f
) in the current directory (.
).git ls-files
lists all files in your git repository.--
ends the options passed togit ls-files
by marking to its parser that no more options to this function will come afterwards. In this way, it knows that everything after--
is going to be a list of file or folder paths.
References:
- The 3 answers I linked to above.
- Where I learned about
nproc
: How to obtain the number of CPUs/cores in Linux from the command line? - My answer on How do I exclude a directory when using
find
?
See also:
- How to find out line-endings in a text file? - use
file
instead ofdos2unix
in the commands above if you just want to see what the line endings currently are for all files in a given directory. - My answer: What are the file limits in Git (number and size)?
- GitHub: Configuring Git to handle line endings
- Another
xargs
example of mine, with the addition of the-I{}
option to specify argument placement: How to unzip multiple files at once...using parallel operations (one CPU core per process, with as many processes as you have cores), into output directories with the same names as the zip files - Sometimes you need to use
bash -c
withxargs
in order to get proper substitution, such as withdirname
. See here: Stack Overflow: Why using dirname in find command gives dots for each match?- I used that trick in some of the
xargs
commands to extract .zip files in my repo here: https://github.com/ElectricRCAircraftGuy/FatFs. See the readme for thosexargs
commands.
- I used that trick in some of the

- 2,562
Use a wildcard. Like this: (If you're in the folder)
dos2unix *
or if you're outside of the folder do:
dos2unix /path/to/folder/*

- 11,688