4

I would like to diff a file system. Currently my bash script prints out the file system recursively into a file (ls -l -R) and diffs it with an expected output.

An example for a line in this file would be: drw---- 100000f3 00000400 0 ./foo/

My current diff command is diff "$TEMP_LOG" "$DIFF_FILE_OUT" --strip-trailing-cr --changed-group-format='%>' --unchanged-group-format='' >> "$SubLog"

As you can see I ignore additional lines in the current output file, I only care about lines that match with the master output.

I now have the problem though that some files may differ in size, or a folder might even have a different name, but due to it's location I know what access rights it should have.

For example:

Output:

------- 00000000 00000000      528 ./foo/bar.txt

Master:

------- 00000000 00000000      200 ./foo/bar.txt

Only the size differs here, and it doesn't matter, I would like to just ignore certain parts of the diff, kind of like an ansi c comment.

Master:
------- 00000000 00000000      /*200*/ ./foo/bar.txt

-- OR --

Master:
d------ 00000000 00000000        /*10*/ ./foo//*123123*///*76456546*//bar.txt

Output:
d------ 00000000 00000000        0 ./foo/asd/sdf/bar.txt

And still have it diff correctly.

Is this even possible with diff, or will I have to write a custom script for it? Since I'm fairly new to cygwin I might be using the completely wrong tool all together, I'm happy for any suggestions.

Update 1:

Taking a step back, here is the general task at hand that I want to achieve. I want to write a script that checks the file system to see if the read/write permissions are set up correctly. The structure of the file system is under my control, so I don't have to worry about it changing too much. Sometimes folders/files might not be present, but if they are their permissions must be checked.

For Example assume that the following is a snapshot of the current file system structure

drw ./foo
drw ./foo/bar
-rw ./foow/bar/bar.txt
drw ./foo/baz
-rw ./foo/baz/baz.txt

And this is what the file system structure might dictate, i.e. if these folders / files are present, the permissions must match.

drw ./foo
drw ./foo/bar
-rw ./foo/bar/bar.txt
--- ./foo/bar/foobar.txt
drw ./foo/baz
-rw ./foo/baz/foobaz.txt

In this case the file system checked out ok, since all files present match their expected values. The situation becomes more complicated as soon as certain folders might have any arbitrary name, only due to their location I know what their permissions should be. Assume that the directory ./foo/bar in the above example might be such a case, i.e. instead of bar the folder could have any name, but still match the -rw permissions.

This seems like a very complicated situation, and I'm not even sure if I can solve it with bash scripting alone. I might have to write an actual application.

Update 2:

Please note that I can not run tools on the file system directly. All I have is a file containing the output of the 'ls -l 'R' command which produces the output as above.

I added some additional parsing of the output, the system / master output now has the format

d------ ./path
drw---- ./path2
6
  • I think you're fixated on "diff" -- what is it that you're trying to compare? What fields you do want, instead of what fields you want to ignore. It will be helpful if you show your input and your desired output. Apr 5, 2012 at 17:45
  • I added an update to the post, I understand what you're saying. Diff might be the completely wrong tool, it just seemed so convenient when I started writing this script.
    – Millianz
    Apr 5, 2012 at 18:00
  • Potential duplicate: superuser.com/questions/31345/… Apr 5, 2012 at 21:45
  • What happens if the files are different? are you updating the file or just the permissions? Apr 5, 2012 at 22:02
  • I don't do anything if I find a difference except warn the user. This is part of a test.
    – Millianz
    Apr 6, 2012 at 16:40

3 Answers 3

1

It maybe easier to abuse rsync to get what you're looking for and potentially do the whole task though you may have to suppress its desire to update the file -- that's the dayjob of rsync anyway:

  • rsync --existing -iprvn a/ b

The options are as follows:

        --existing              skip creating new files on receiver
    -p, --perms                 preserve permissions
    -i, --itemize-changes       output a change-summary for all updates
    -r, --recursive             recurse into directories
    -v, --verbose               increase verbosity
    -n, --dry-run               perform a trial run with no changes made

Now let's create a test. Here we have two directories, both have a file the other doesn't have; b also has a+x on 1.

$ ls -lah a/ b/
a/:
total 8.0K
drwxrwxr-x  2 ecarroll ecarroll 4.0K Apr  5 16:38 .
drwxr-xr-x 71 ecarroll ecarroll 4.0K Apr  5 16:38 ..
-rw-rw-r--  1 ecarroll ecarroll    0 Apr  5 16:38 1
-rw-rw-r--  1 ecarroll ecarroll    0 Apr  5 16:38 2
-rw-rw-r--  1 ecarroll ecarroll    0 Apr  5 16:38 5

b/:
total 8.0K
drwxrwxr-x  2 ecarroll ecarroll 4.0K Apr  5 16:52 .
drwxr-xr-x 71 ecarroll ecarroll 4.0K Apr  5 16:38 ..
-rwxrwxr-x  1 ecarroll ecarroll    0 Apr  5 16:52 1
-rw-rw-r--  1 ecarroll ecarroll    0 Apr  5 16:52 5
-rw-rw-r--  1 ecarroll ecarroll    0 Apr  5 16:38 7

Now let's run an rsync.

$ rsync --existing -icprvn a/ b
sending incremental file list
.f...p..... 1

sent 97 bytes  received 15 bytes  224.00 bytes/sec
total size is 0  speedup is 0.00 (DRY RUN)
  • f means it's a file.
  • p means the permissions are off.
  • 1 is just the name of my example file.
2
  • Sadly I can't run rsync on the file system directly. All I have is the 2 files, one is the output of the file system and one is the expected output. I don't think this works in this case.
    – Millianz
    Apr 6, 2012 at 16:40
  • How do you get access to the directory? How come you can't run rsync on that machine Apr 6, 2012 at 19:43
-1

I think all you need is:

find . -type f -printf "%M %p\n"

Given that, you can probably write to a file and use diff.

http://manpages.debian.net/cgi-bin/man.cgi?query=find

-1

If you only want the permissions part of ls, you could just parse it out with awk.

ls -l your-file | awk '{print $1;}'

Alternately you can check permissions in a PHP script using the fileperms function.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .