# How to obtain the result of a diff between 2 files in a loop?

**URL:** <https://discourse.julialang.org/t/how-to-obtain-the-result-of-a-diff-between-2-files-in-a-loop/23784>\
**Category:** General Usage\
**Created:** [May 2, 2019, 5:00pm UTC](https://discourse.julialang.org/t/how-to-obtain-the-result-of-a-diff-between-2-files-in-a-loop/23784 "2019-05-02T17:00:10Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![steph\_de\_paris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/steph_de_paris/32/7780_2.png) [@steph\_de\_paris](https://discourse.julialang.org/u/steph_de_paris)\
**Post date:** [May 2, 2019, 5:00pm UTC](https://discourse.julialang.org/t/how-to-obtain-the-result-of-a-diff-between-2-files-in-a-loop/23784/1 "2019-05-02T17:00:10Z")

</div>

Hello,

I would like to compare in a loop files and to obtain the result through an integer (1=OK, 0=FALSE).

I use the following code:

```julia
for n in 1:10
   run(`diff file_a file_b`)
end

```

If the 2 files file\_a and file\_b are identical, the code is OK. If the 2 fils are different, the code gives an error.

Is it possible to have a “clean” code wich gives an int or a boolean in function of the result of the shell diff command in the previous loop ?

Or is there another way to code such test ?

Thanks.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [May 2, 2019, 5:35pm UTC](https://discourse.julialang.org/t/how-to-obtain-the-result-of-a-diff-between-2-files-in-a-loop/23784/2 "2019-05-02T17:35:40Z")

</div>

You’ll want to use `success` to test command success, rather than `run`:

```julia
success(`diff file_a file_b`)

```

Note that if all you want to know if whether they differ or not, you may want to use the UNIX `cmp` command instead:

```julia
if success(`cmp --quiet file_a file_b`)
    # they are the same
else
    # they are different
end

```

---

<div class="post-metadata">

**Author:** ![steph\_de\_paris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/steph_de_paris/32/7780_2.png) [@steph\_de\_paris](https://discourse.julialang.org/u/steph_de_paris)\
**Post date:** [May 2, 2019, 6:30pm UTC](https://discourse.julialang.org/t/how-to-obtain-the-result-of-a-diff-between-2-files-in-a-loop/23784/3 "2019-05-02T18:30:17Z")

</div>

Thanks ! 🙂

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [May 3, 2019, 1:38am UTC](https://discourse.julialang.org/t/how-to-obtain-the-result-of-a-diff-between-2-files-in-a-loop/23784/4 "2019-05-03T01:38:15Z")

</div>

> [@StefanKarpinski](#):
>
> `if success(`cmp --quiet file_a file_b`)`

`--quiet` is a GNU-ism; if you want it to work with any POSIX `cmp` you should use `-s`.

Of course, this won’t work on Windows. It would be pretty easy to write an equivalent Julia function, though, like:

```julia
function filecmp(path1::AbstractString, path2::AbstractString)
    stat1, stat2 = stat(path1), stat(path2)
    if !(isfile(stat1) && isfile(stat2)) || filesize(stat1) != filesize(stat2)
        return false # or should it throw if a file doesn't exist?
    end
    stat1 == stat2 && return true # same file
    open(path1, "r") do file1
        open(path2, "r") do file2
            buf1 = Vector{UInt8}(undef, 32768)
            buf2 = similar(buf1)
            while !eof(file1) && !eof(file2)
                n1 = readbytes!(file1, buf1)
                n2 = readbytes!(file2, buf2)
                n1 != n2 && return false
                0 != Base._memcmp(buf1, buf2, n1) && return false
            end
            return eof(file1) == eof(file2)
        end
    end
end

```

Not only is this more portable, it is also _much_ faster than executing an external program like `cmp`. On my Mac laptop it is about 1000× faster in the common case where the file sizes differ, and about 60× faster for a 20kB file when the files match (so that the whole files need to be read).

(Python provides [`filecmp.cmp`](https://docs.python.org/3.7/library/filecmp.html) in its standard library, I wonder if Julia should too?)

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [May 3, 2019, 11:09am UTC](https://discourse.julialang.org/t/how-to-obtain-the-result-of-a-diff-between-2-files-in-a-loop/23784/5 "2019-05-03T11:09:59Z")

</div>

> [@stevengj](#):
>
> (Python provides [`filecmp.cmp`](https://docs.python.org/3.7/library/filecmp.html) in its standard library, I wonder if Julia should too?)

Probably a good idea. Worth opening an issue for.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [May 3, 2019, 11:32am UTC](https://discourse.julialang.org/t/how-to-obtain-the-result-of-a-diff-between-2-files-in-a-loop/23784/6 "2019-05-03T11:32:52Z")

</div>

Are you sure this should be in stdlib? Just a package would be fine IMO.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [May 3, 2019, 11:38am UTC](https://discourse.julialang.org/t/how-to-obtain-the-result-of-a-diff-between-2-files-in-a-loop/23784/7 "2019-05-03T11:38:06Z")

</div>

True, it’s on the border between basic enough to include in stdlib and not-needed-often-enough to belong in stdlib. On the other hand, what I like about it is that the API is absolutely crystal clear and won’t change—comparing two files to see if they’re bit-for-bit identical is always going to mean the same thing.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [May 3, 2019, 12:35pm UTC](https://discourse.julialang.org/t/how-to-obtain-the-result-of-a-diff-between-2-files-in-a-loop/23784/8 "2019-05-03T12:35:22Z")

</div>

> [@StefanKarpinski](#):
>
> comparing two files to see if they’re bit-for-bit identical is always going to mean the same thing

Until feature requests are opened for perfectly reasonable extensions 😉 Eg even the dead simple shell command `cmp` can ignore initial regions, compare up to a given number of bytes, etc.

I don’t indend to be nitpicking here; just given how labor intensive extending anything in `Base` & the standard libraries is (ramifications, reviews), I am very much against making something an stdlib unless there is a compelling reason.

In any case, the effort can certainly _start_ as a package.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [May 3, 2019, 12:57pm UTC](https://discourse.julialang.org/t/how-to-obtain-the-result-of-a-diff-between-2-files-in-a-loop/23784/9 "2019-05-03T12:57:37Z")

</div>

All fair points!

---

<div class="post-metadata">

**Author:** ![Per](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/per/32/10387_2.png) [@Per](https://discourse.julialang.org/u/Per)\
**Post date:** [May 3, 2019, 1:15pm UTC](https://discourse.julialang.org/t/how-to-obtain-the-result-of-a-diff-between-2-files-in-a-loop/23784/10 "2019-05-03T13:15:26Z")

</div>

> [@StefanKarpinski](#):
>
> comparing two files to see if they’re bit-for-bit identical is always going to mean the same thing

There are a couple of variations of what it can mean for files to be “identical”:

- a and b are different files, that happen to contain identical data
- a and b are hard-linked to the same inode
- a is a symlink to b, or vice versa
- a and b are actually the same file (but the path might be different, e.g. due to symlinked directories).

All of these scenarios would count as “bit-for-bit identical” but a `filecmp` function should offer the possibility to distinguish between them.

I wrote some code for this kind of thing once upon a time. MIT license, if anyone wants to copy from it: [GitHub - perrutquist/DeduplicateFiles.jl: Julia functions for finding and removing duplicate files.](https://github.com/perrutquist/DeduplicateFiles.jl)

---

<div class="post-metadata">

**Author:** ![mroavi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mroavi/32/8804_2.png) [@mroavi](https://discourse.julialang.org/u/mroavi)\
**Post date:** [February 24, 2021, 3:48pm UTC](https://discourse.julialang.org/t/how-to-obtain-the-result-of-a-diff-between-2-files-in-a-loop/23784/11 "2021-02-24T15:48:39Z")

</div>

How can I capture the output of `diff` (the lines that are different) in a Julia variable?

I tried using `read(command::Cmd, String)` but it fails since diff exits with an error whenever the two files are different.

Edit: I found a way:

```julia
diff_output = read(ignorestatus(`diff $file1 $file2`), String)

```

---

<div class="post-metadata">

**Author:** ![oxinabox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oxinabox/32/206603_2.png) [@oxinabox](https://discourse.julialang.org/u/oxinabox)\
**Post date:** [February 24, 2021, 5:34pm UTC](https://discourse.julialang.org/t/how-to-obtain-the-result-of-a-diff-between-2-files-in-a-loop/23784/12 "2021-02-24T17:34:27Z")

</div>

In general people looking at this question are likely interested in DeepDiffs.jl  
Which is much older than this question, so I am surprised it isn’t mentioned already

> **[GitHub - ssfrr/DeepDiffs.jl: Compute and pretty-print diffs for data...](https://github.com/ssfrr/DeepDiffs.jl)**
>
> Compute and pretty-print diffs for data structures like arrays and dictionaries - GitHub - ssfrr/DeepDiffs.jl: Compute and pretty-print diffs for data structures like arrays and dictionaries

Applying it to files can be done via comaring `eachline(file1)`, `eachline(file2)`

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [February 24, 2021, 5:44pm UTC](https://discourse.julialang.org/t/how-to-obtain-the-result-of-a-diff-between-2-files-in-a-loop/23784/13 "2021-02-24T17:44:19Z")

</div>

Or also

> **[GitHub - simeonschaub/DiffUtils.jl: Julia interface for GNU Diffutils](https://github.com/simeonschaub/DiffUtils.jl)**
>
> Julia interface for GNU Diffutils. Contribute to simeonschaub/DiffUtils.jl development by creating an account on GitHub.

---

<div class="post-metadata">

**Author:** ![Betristor](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/betristor/32/45264_2.png) [@Betristor](https://discourse.julialang.org/u/Betristor)\
**Post date:** [January 12, 2024, 7:33am UTC](https://discourse.julialang.org/t/how-to-obtain-the-result-of-a-diff-between-2-files-in-a-loop/23784/14 "2024-01-12T07:33:27Z")

</div>

I used this in julia 1.10, but it seems that new \_memcmp now uses pointer instead of higher data structure Vector to compare. This will now throw an error of in julia 1.10. While before julia 1.9.4, this function works fine all the time. The logs are as following

```julia
MethodError: no method matching _memcmp(::Vector{UInt8}, ::Vector{UInt8}, ::Int64)

Closest candidates are:
  _memcmp(::Union{Ptr{UInt8}, AbstractString}, ::Union{Ptr{UInt8}, AbstractString}, ::Int64)
   @ Base strings/string.jl:129

```

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [January 12, 2024, 2:09pm UTC](https://discourse.julialang.org/t/how-to-obtain-the-result-of-a-diff-between-2-files-in-a-loop/23784/15 "2024-01-12T14:09:29Z")

</div>

> [@Betristor](#):
>
> used this in julia 1.10, but it seems that new \_memcmp now uses pointer instead of higher data structure Vector to compare.

Yeah, in the longer run if you are using this sort of code you should really write it using documented APIs. Fortunately, calling `memcmp` is on a `Vector{UInt8}` is just a 1-line function:

```julia
_memcmp(a::Vector{UInt8}, b::Vector{UInt8}) = length(a) == length(b) &&
    Bool(iszero(ccall(:memcmp, Cint, (Ptr{UInt8}, Ptr{UInt8}, Csize_t), a, b, length(a) % Csize_t)))

```
