Differences between revisions 7 and 30 (spanning 23 versions)
Revision 7 as of 2007-11-22 04:24:52
Size: 1083
Editor: s20
Comment: Hi!, <a href="http://www.mc-subway.cn/chairs/map.html">chairs </a>[url="http://www.mc-subway.cn/chairs/map.html"]chairs [/url]http://www.mc-subway.cn/chairs/map.html chairs %-D, <a href="http://www.m
Revision 30 as of 2012-09-21 12:59:35
Size: 3659
Editor: 87-126-38-189
Comment:
Deletions are marked like this. Additions are marked like this.
Line 1: Line 1:
Hi!, <a href="http://www.mc-subway.cn/chairs/map.html">chairs
</a>[url="http://www.mc-subway.cn/chairs/map.html"]chairs
[/url]http://www.mc-subway.cn/chairs/map.html chairs
 %-D, <a href="http://www.mc-subway.cn/chairs/map.html">chairs
</a>[url="http://www.mc-subway.cn/chairs/map.html"]chairs
[/url]http://www.mc-subway.cn/chairs/map.html chairs
 uzokp, <a href="http://www.netberg.cn/frames/map.html">frames
</a>[url="http://www.netberg.cn/frames/map.html"]frames
[/url]http://www.netberg.cn/frames/map.html frames
 927, <a href="http://www.cannabin.cn/lamps/map.html">lamps
</a>[url="http://www.cannabin.cn/lamps/map.html"]lamps
[/url]http://www.cannabin.cn/lamps/map.html lamps
 njc, <a href="http://www.mcparking.cn/pumps/map.html">pumps
</a>[url="http://www.mcparking.cn/pumps/map.html"]pumps
[/url]http://www.mcparking.cn/pumps/map.html pumps
 18187, <a href="http://www.mcfreestyle.cn/uniform/map.html">uniform</a>[url="http://www.mcfreestyle.cn/uniform/map.html"]uniform[/url]http://www.mcfreestyle.cn/uniform/map.html uniform doihy,
----
CategoryCategory
<<Anchor(faq87)>>
== How can I get a file's permissions (or other metadata) without parsing ls -l output? ==
There are several potential ways, most of which are system-specific. They also depend on precisely ''why'' you want the information; in most cases, there will be some other way to accomplish your [[XyProblem|real goal]]. You [[ParsingLs|don't want to parse ls's output]] if there's any possible way to avoid doing so.

Many of the cases where you might ask about permissions -- such as ''I want to find any files with the setuid bit set'' -- can be handled with [[UsingFind#permissions|the find(1) command]].

For some questions, such as ''I want to make sure this file has 0644 permissions'', you don't actually need to ''check'' what the permissions are. You can just use `chmod 0644 myfile` and set them directly. And if you DO actually need to check what the permissions are instead of forcing them, then you can use "find -perm".

If you want to see whether you can read, write or execute a file, there are `test -r`, `-x` and `-w`.

If you want to see whether a file is zero bytes in size or not, you don't need to read the file's size into a variable. You can just use `test -s` instead.

If you want to copy the modification time from one file to another, you can use `touch -r`. The `chown` command on some GNU/Linux systems has a `--reference` option that works the same way, letting you copy the owner and group from one file to another.

If your needs aren't met by any of those, and you really feel you ''must'' extract the metadata from a file into a variable, then we can look at a few alternatives:

 * On GNU/Linux systems, *BSD and possibly others, there is a command called `stat(1)`. On older GNU/Linux systems, this command takes no options -- just a filename -- and you will have to parse its output.
 {{{
 $ stat /
   File: "/"
   Size: 1024 Filetype: Directory
   Mode: (0755/drwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
 Device: 8,0 Inode: 2 Links: 25
 Access: Wed Oct 17 14:58:02 2007(00000.00:00:01)
 Modify: Wed Feb 28 15:42:14 2007(00230.22:15:49)
 Change: Wed Feb 28 15:42:14 2007(00230.22:15:49)
 }}}
 In this case, one could extract the 0755 from the `Mode:` line, using `awk` or similar commands.

 * On newer GNU/Linux and FreeBSD systems, the `stat` command takes arguments which allow you to specify which information you want:
 {{{
 $ stat -c %a /
 755
 }}}
 That's obviously a lot easier to parse. (NetBSD and OpenBSD use `-f` instead of `-c`, and have entirely different format strings.)

 * On systems with perl 5, you can use:
 {{{
 perl -e 'printf "%o\n", 07777 & (stat $ARGV[0])[2]' "$filename"
 }}}
 This returns the same octal string that the `stat -c %a` example does, but is far more portable. (And slower.)

 * Sufficiently recent GNU `find` has a `-printf` switch that can print out metadata instead of filenames:
 {{{
 find "$filename" -maxdepth 0 -printf %m
 }}}
 (Very, very non-portable. But if you happen to need a whole bunch of metadata, recursively....)

 * If your bash is compiled with [[BashLoadable|loadable builtin support]], you can build the `finfo` builtin (type `make` in the `examples/loadables/` subdirectory of your bash source tree), `enable` it, and then use:
 {{{
 $ finfo -o .bashrc
 644
 }}}
 Beware that the `finfo.c` distributed with bash up through 4.0 contains at least one bug (in the `-s` option), so the code has clearly not been tested much. Most precompiled bash packages do not include compiled examples, so this may be a difficult alternative for most users.

How can I get a file's permissions (or other metadata) without parsing ls -l output?

There are several potential ways, most of which are system-specific. They also depend on precisely why you want the information; in most cases, there will be some other way to accomplish your real goal. You don't want to parse ls's output if there's any possible way to avoid doing so.

Many of the cases where you might ask about permissions -- such as I want to find any files with the setuid bit set -- can be handled with the find(1) command.

For some questions, such as I want to make sure this file has 0644 permissions, you don't actually need to check what the permissions are. You can just use chmod 0644 myfile and set them directly. And if you DO actually need to check what the permissions are instead of forcing them, then you can use "find -perm".

If you want to see whether you can read, write or execute a file, there are test -r, -x and -w.

If you want to see whether a file is zero bytes in size or not, you don't need to read the file's size into a variable. You can just use test -s instead.

If you want to copy the modification time from one file to another, you can use touch -r. The chown command on some GNU/Linux systems has a --reference option that works the same way, letting you copy the owner and group from one file to another.

If your needs aren't met by any of those, and you really feel you must extract the metadata from a file into a variable, then we can look at a few alternatives:

  • On GNU/Linux systems, *BSD and possibly others, there is a command called stat(1). On older GNU/Linux systems, this command takes no options -- just a filename -- and you will have to parse its output.

     $ stat /
       File: "/"
       Size: 1024         Filetype: Directory
       Mode: (0755/drwxr-xr-x)         Uid: (    0/    root)  Gid: (    0/    root)
     Device:  8,0   Inode: 2         Links: 25   
     Access: Wed Oct 17 14:58:02 2007(00000.00:00:01)
     Modify: Wed Feb 28 15:42:14 2007(00230.22:15:49)
     Change: Wed Feb 28 15:42:14 2007(00230.22:15:49)

    In this case, one could extract the 0755 from the Mode: line, using awk or similar commands.

  • On newer GNU/Linux and FreeBSD systems, the stat command takes arguments which allow you to specify which information you want:

     $ stat -c %a /
     755

    That's obviously a lot easier to parse. (NetBSD and OpenBSD use -f instead of -c, and have entirely different format strings.)

  • On systems with perl 5, you can use:
     perl -e 'printf "%o\n", 07777 & (stat $ARGV[0])[2]' "$filename"

    This returns the same octal string that the stat -c %a example does, but is far more portable. (And slower.)

  • Sufficiently recent GNU find has a -printf switch that can print out metadata instead of filenames:

     find "$filename" -maxdepth 0 -printf %m
    (Very, very non-portable. But if you happen to need a whole bunch of metadata, recursively....)
  • If your bash is compiled with loadable builtin support, you can build the finfo builtin (type make in the examples/loadables/ subdirectory of your bash source tree), enable it, and then use:

     $ finfo -o .bashrc
     644

    Beware that the finfo.c distributed with bash up through 4.0 contains at least one bug (in the -s option), so the code has clearly not been tested much. Most precompiled bash packages do not include compiled examples, so this may be a difficult alternative for most users.

BashFAQ/087 (last edited 2015-09-28 19:14:40 by GreyCat)