[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: chmod bug

From: Bob Proulx
Subject: Re: chmod bug
Date: Tue, 23 Jul 2002 00:42:50 -0600
User-agent: Mutt/1.4i

> There's apparently a bug with chmod's use of recursion.  Apparently, it
> doesn't work.

Thanks for the report.  But actually you have a misunderstanding of
how the -R options to the utils commands function.

> Let's say I have a directory called 'test', with three subdirectories
> called 'alpha', 'bravo', and 'charlie'.  Each subdirectory has two files in
> it: 'alpha' has 'a1.txt' and 'a2.txt', 'bravo' has 'b1.txt' and 'b2.txt',
> and 'charlie' has 'c1.txt' and 'c2.txt'.  All directories have permissions
> 775 and all files have permissions 644.
> If I'm in 'test' and do:
>  chmod -R 777 *.txt
> I get the message:
>  chmod: getting attributes of `*.txt': No such file or directory
> If I put a file called 't1.txt' in the 'test' directory, and do the same
> command, then 't1.txt' gets set to 777 (-rwxrwxrwx), and the error message
> above does not appear, but none of the files in 'alpha', 'bravo', or
> 'charlie' get their permissions set to 777.

An excellent description!  It is rare for people submitting reports to
create such well written report of what they are seeing.

> Please let me know if you need any more information about this bug.

Let's check out the info page for chmod.

  info chmod

     chmod [OPTION]... {MODE | --reference=REF_FILE} FILE...

       Recursively change permissions of directories and their contents.

So it does recursively change permissions.  But only for directories
and their contents.  Therefore this only has an effect if directories
are listed on the command line.  Technically correct but a subtle
combination.  You were not putting any directories on the command
line.  Therefore it did not recursively follow down any directories
since it did not see any directories.

More generally people confuse the *.txt type of file globbing that the
shell does with the directory recursion that the commands do.  Those
are two different things.  Use the echo command to see what the chmod
command is seeing in those two cases.

  mkdir /tmp/chmod-test && cd /tmp/chmod-test
  echo *.txt
  echo chmod ug+wx *.txt
  touch foo.txt
  echo *.txt
  echo chmod ug+wx *.txt
  echo foo.txt
  echo chmod ug+wx foo.txt

As you can see the results of the echo are different in the different
cases.  When no file matches then the * is not expanded.  This is what
is happening when it says "No such file or directory" in your example.
But when the file is there it is expanded to be the filename by the
shell, probably /bin/bash in your case.

The shell expands command line wildcards before invoking the command.
The command never sees the '*.txt' and has no idea that you typed that
in on the command line.  The command cannot traverse the filesystem
trying to find files that match that pattern.  It did not know that
you typed in a pattern.  In the example above from the result can you
see that the command cannot in any way tell that one line used a
wildcard 'chmod ug+wx *.txt' and another did not 'chmod ug+wx foo.txt'?

What you are probably wanting to do is to use the -R on directories.

  chmod -R 777 .

Except that is a terrible thing to do with 777 but it fits your
example.  But please do read about a+X, that 'X' was exactly what this
was designed for.  You really don't want to make all of your files
executable and you probably don't want to make them world writable.
Since I like the symbolic permissions, here is an example that is a
little safer.

  chmod -R a+X,ug+rw .

Really the unix philosophy is of small modular programs which work
together to create more complex programs.  Since you are wanting to
find all of the files that match *.txt you should be using the 'find'
program instead.

  find . -name '*.txt' -print

If only there were some way to operate on those files.  Wait, there
is!  Check this out.  Take the output of the find command and put it
on the command line as a list of files for the chmod command to
operate upon.

  chmod a+x $(find . -name '*.txt' -print)

Same as the following but using the newer syntax.  (One can nest and
the other can't easily.)

  chmod a+x `find . -name '*.txt' -print`

That works on small directories.  But on large directories you will
run into operating system limitations.  You will overrun your
environment space and the command will fail.  And it also does not
work when filenames contain embedded newlines.  Mostly people don't
create filenames like that on unix machines but because of the windows
influence we should be prepared for them.

  find . -name '*.txt' -print0 | xargs -0 chmod a+x

That works for any size of directory for any filename.  The strings
are zero terminated (-print0 and -0 options) so newlines won't fool
the commands.

This is actually an FAQ.  Check out this web pointer.  Search for "Why
don't the utilities have built in directory recursion?"



reply via email to

[Prev in Thread] Current Thread [Next in Thread]