Re: GNU find: "print0" and "-type" arguments
Martin Steigerwald wrote: > Bob Proulx: > > Martin Steigerwald wrote: > > > martin@merkaba:~/Zeit/find-Test> find \( -type d -print \) -o \( > > > -name "file" -printf "%s %p" \) -o \( -name "anotherfile" -print0 > > > \) . > > > ./anotherfile./dir > > > 0 ./file% > > > martin@merkaba:~/Zeit/find-Test> > > > > It is inconsistent to mix -print0 with -print and -printf. Just use > > one or the other consistently. > > Well I wanted to know which action find uses in each case, had I used - > print in all the case, I could not tell a difference. In that case I suggest using -printf throughout. Put an identifying remark in the printf format string associated with that action. For example: $ find . -type d -printf "%p due to -type d\n" -o -name file -printf "%p due to -name file\n" -o -name anotherfile -printf "%p due to -name anotherfile\n" . due to -type d ./file due to -name file ./anotherfile due to -name anotherfile ./dir due to -type d How is that? > Yes, my understanding was find would be doing one run for each action, > thus first dearch for »-type d« and print it, then search again for »-name > "file« and print it and so on, but then it needed to scan the directory > three times instead of just once. Correct. > So I teach people this stuff and upto now didn´t think deeply about the > exact order. I knew that the action follows the search criteria, but I > never thought about the case with mutiple actions on one line. The argument list is a small program that is interpreted for each file entry. You write the argument list as you would write a program. > So another interesting use case: > > martin@merkaba:~/Zeit/find-Test> find -printf "%s %p\n" -print -exec ls -ld > {} \; -delete My first thought was "ew.." due to the "-delete" being mixed in with the recursive operation and without any restriction. That is basically the same as 'rm -rf .' and feels very dangerous to me. (Which of course won't delete '.' but will delete everything else below it.) It could delete a lot of files very quickly! > martin@merkaba:~/Zeit/find-Test> find > . > martin@merkaba:~/Zeit/find-Test> Yes. > So find execute all four actions for each search result and all the > results are gone then. Yes. Each action returned true. The print actions always return true. The exec action will pass back the exit code of the process. If any return code is not true then the processing left to right over the argument list will stop. > Nice ;) As long as that is what you wanted! :-) > All results except for the current directory »find-Test«, which the - > delete option didn´t touch. The manpage is not clear. It writes about > deleting files, but it »-delete« also removes empty directories. And it > leaves the current directory alone although it is in the search results. Of course '.' won't be removed since it can't be. This is the same as with 'rm -rf .' too. (However I see that recent 'rm' doesn't allow that use nad prints an error and exits. Probably a good safe behavior.) I personally only use -delete with a specific restriction such as with a -type f or -name file1 or other type of specific targeting. I avoid having find recursively walk down directories and also have -delete recursively walk down directories too. It also feels wrong that it is recursively deleting directories that find will in the future recurse down. Due to buffering I think this won't be visible with small directories. But with large directories I believe (but did not test) that it will produce an error when find tries to read a directory that has been previously deleted in passing. Using -delete automatically enables -depth. Therefore the order of file processing will be the order find would use with 'find . -depth'. This is done to avoid trying to delete a directory that still contains files. Using -depth gives the possibility that the directory will be emptied first. $ mkdir dir $ touch dir/otherfile $ find . -type d -print -delete ./dir find: cannot delete `./dir': Directory not empty . $ find . -print . ./dir ./dir/otherfile $ find . -depth -print ./dir/otherfile ./dir . Bob signature.asc Description: Digital signature
Re: GNU find: "print0" and "-type" arguments
Am Freitag, 3. August 2012 schrieb Bob Proulx: > Martin Steigerwald wrote: > > martin@merkaba:~/Zeit/find-Test> find \( -type d -print \) -o \( > > -name "file" -printf "%s %p" \) -o \( -name "anotherfile" -print0 > > \) . > > ./anotherfile./dir > > 0 ./file% > > martin@merkaba:~/Zeit/find-Test> > > It is inconsistent to mix -print0 with -print and -printf. Just use > one or the other consistently. Well I wanted to know which action find uses in each case, had I used - print in all the case, I could not tell a difference. > > Which is the same as without braces: > > > > martin@merkaba:~/Zeit/find-Test> find -type d -print -o -name "file" > > -printf "%s %p" -o -name "anotherfile" -print0 . > > ./anotherfile./dir > > 0 ./file% > > Yes. > > > Now I am wondering about the order. > > > > Why does find print "another file" before ".dir" and "file" after > > "another file"? > > You seem to be missing the basic operation of find. The find program > iterates across ever file and processes arguments from left to right > for that file. As long as the action returns true then find continues > to process arguments from left to right. If any argument returns > false then processing stops for that file. Find then proceeds to the > next file and restarts processing arguments for the next file from > left to right. Yes, my understanding was find would be doing one run for each action, thus first dearch for »-type d« and print it, then search again for »-name "file« and print it and so on, but then it needed to scan the directory three times instead of just once. > find -type d -print -o -name "file" -printf "%s %p" -o -name > "anotherfile" -print0 > > For every file find processes it walks across the argument list. For > your example arguments it is something like this: > > for each file do > if type d then > print > else > if name "file" then > printf "%s %p" > else > if name "anotherfile" then > print0 > end > end > end > end > > Also 'find' walks through the directory in the order of the entries in > the list. It doesn't sort the entries first. This means that they > are in an arbitrary order. They might appear in any order but the > order will be repeatable for that particular directory. Your explaination perfectly makes sense. So I teach people this stuff and upto now didn´t think deeply about the exact order. I knew that the action follows the search criteria, but I never thought about the case with mutiple actions on one line. So another interesting use case: martin@merkaba:~/Zeit/find-Test> find -printf "%s %p\n" -print -exec ls - ld {} \; -delete 0 ./anotherfile ./anotherfile -rw-r--r-- 1 martin martin 0 Aug 2 19:57 ./anotherfile 4096 ./dir ./dir drwxr-xr-x 2 martin martin 4096 Aug 2 19:56 ./dir 0 ./file ./file -rw-r--r-- 1 martin martin 0 Aug 2 19:56 ./file 4096 . . drwxr-xr-x 2 martin martin 4096 Aug 3 15:27 . martin@merkaba:~/Zeit/find-Test> find . martin@merkaba:~/Zeit/find-Test> So find execute all four actions for each search result and all the results are gone then. Nice ;) All results except for the current directory »find-Test«, which the - delete option didn´t touch. The manpage is not clear. It writes about deleting files, but it »-delete« also removes empty directories. And it leaves the current directory alone although it is in the search results. Thanks, -- Martin 'Helios' Steigerwald - http://www.Lichtvoll.de GPG: 03B0 0D6C 0040 0710 4AFA B82F 991B EAAC A599 84C7 -- To UNSUBSCRIBE, email to debian-user-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org Archive: http://lists.debian.org/201208031534.02823.mar...@lichtvoll.de
Re: GNU find: "print0" and "-type" arguments
Martin Steigerwald wrote: > martin@merkaba:~/Zeit/find-Test> find \( -type d -print \) -o \( -name "file" > -printf "%s %p" \) -o \( -name "anotherfile" -print0 \) > . > ./anotherfile./dir > 0 ./file% > > martin@merkaba:~/Zeit/find-Test> It is inconsistent to mix -print0 with -print and -printf. Just use one or the other consistently. > Which is the same as without braces: > > martin@merkaba:~/Zeit/find-Test> find -type d -print -o -name "file" -printf > "%s %p" -o -name "anotherfile" -print0 > . > ./anotherfile./dir > 0 ./file% Yes. > Now I am wondering about the order. > > Why does find print "another file" before ".dir" and "file" after "another > file"? You seem to be missing the basic operation of find. The find program iterates across ever file and processes arguments from left to right for that file. As long as the action returns true then find continues to process arguments from left to right. If any argument returns false then processing stops for that file. Find then proceeds to the next file and restarts processing arguments for the next file from left to right. find -type d -print -o -name "file" -printf "%s %p" -o -name "anotherfile" -print0 For every file find processes it walks across the argument list. For your example arguments it is something like this: for each file do if type d then print else if name "file" then printf "%s %p" else if name "anotherfile" then print0 end end end end Also 'find' walks through the directory in the order of the entries in the list. It doesn't sort the entries first. This means that they are in an arbitrary order. They might appear in any order but the order will be repeatable for that particular directory. Bob signature.asc Description: Digital signature
Re: GNU find: "print0" and "-type" arguments
Hi! Bill Unruh allowed me to post his personal answer to the list. He answered personally cause otherwise he would get the whole mailing list in the mail instead due to some newsgroup gateway stuff. On Thursday, 2. August 2012 he wrote: > In linux.debian.user, you wrote: > > Am Donnerstag, 2. August 2012 schrieb Bob Proulx: > >> > I see (on a terminal screen that does not display null > >> > characters): ../dir./file > >> > >> You have the order of arguments backwards. You wanted to say this: > >> find -type d -print > >> > >> That would do the right thing. Doing it the other way around > >> doesn't make any sense. > > Sure it makes sense. It says, take the name print it, then if that is > successful, test if it is a directory. > Thus > find -ls -type d -print > will list all files, and those are directories will then print it as > well. > o > Eg here is part of the output from that command. Note that all of the > directories have both the ls -l listing and the name printed out, while > the files only have the first. > > Of course if by "it does not make sense" you meant that if the -type d > was at the end of the list of find commands, it would have no > consequences for the output, then you are right. > > > 4203774 drwxrwx--- 2 unruhunruh4096 Jul 25 17:22 > ./.urpmi-500/rpms ./.urpmi-500/rpms > 293597 172 -r--r--r-- 1 root root 175070 May 18 14:20 > ./acroread-plugins-weblink-9.4.6-0.1-mdv2011.0.i586.rpm 2766824 > drwx-- 4 root root 4096 Jul 31 12:05 > ./systemd-namespace-cBR4sm ./systemd-namespace-cBR4sm I thought find would work that way first and then chose to think otherwise due to my own tests which didn´t take the implicit "and" in account: > > I think doing it the other way around will just use -print0 on > > everything since no criteria yet specified and then apply the filter > > and then probably do nothing as an action has already been specified > > (hence no implicite -print at the end). > > > > Well more so, find seems to stop at the first action: > > > > martin@merkaba:~/Zeit> mkdir find-Test > > martin@merkaba:~/Zeit> cd find-Test > > martin@merkaba:~/Zeit/find-Test> ls > > martin@merkaba:~/Zeit/find-Test> mkdir dir > > martin@merkaba:~/Zeit/find-Test> touch file > > martin@merkaba:~/Zeit/find-Test> touch anotherfile > > martin@merkaba:~/Zeit/find-Test> find -type d -print -name "file" > > -printf "%s %p" -name "anotherfile" -print0 > > Uh, remember that any entry goes through the list. Thus the -type d > weeks out everything but directories and applies the following criteia > to that. The rule is that there is an implicit "and" between the items. > > find -type d "and" -print "and" -name file "and" -print "%s %p" "and" > -name "anotherfile" "and" -print0 > > There is no file whose name is both file and anotherfile. So, on the > direcory "dir" it passes the first test, it passes the second test > (which is "have I printed it out") it fails the third, and the > terminates the commmands because of the logical "and" > On "file" it fails the first test, since it is not a directory. On > anotherfile similarly. > f you wanted "or" ratehr than "and" you have to explicitly put in a -o > (for or) between the tests. > > find (-type d -print) -o ( -name "file" -printf "%s %p" ) -o ( -name > "anotherfile" -print0 ) With some escaping gives: martin@merkaba:~/Zeit/find-Test> find \( -type d -print \) -o \( -name "file" -printf "%s %p" \) -o \( -name "anotherfile" -print0 \) . ./anotherfile./dir 0 ./file% martin@merkaba:~/Zeit/find-Test> Which is the same as without braces: martin@merkaba:~/Zeit/find-Test> find -type d -print -o -name "file" - printf "%s %p" -o -name "anotherfile" -print0 . ./anotherfile./dir 0 ./file% Now I am wondering about the order. Why does find print "another file" before ".dir" and "file" after "another file"? Bill in case you have an idea I´d happily post your answer to the list once again if you allow me ;) Regards, -- Martin 'Helios' Steigerwald - http://www.Lichtvoll.de GPG: 03B0 0D6C 0040 0710 4AFA B82F 991B EAAC A599 84C7 -- To UNSUBSCRIBE, email to debian-user-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org Archive: http://lists.debian.org/201208022246.31737.mar...@lichtvoll.de
Re: GNU find: "print0" and "-type" arguments
Am Donnerstag, 2. August 2012 schrieb Bob Proulx: > > I see (on a terminal screen that does not display null characters): > > ../dir./file > > You have the order of arguments backwards. You wanted to say this: > > find -type d -print > > That would do the right thing. Doing it the other way around doesn't > make any sense. I think doing it the other way around will just use -print0 on everything since no criteria yet specified and then apply the filter and then probably do nothing as an action has already been specified (hence no implicite -print at the end). Well more so, find seems to stop at the first action: martin@merkaba:~/Zeit> mkdir find-Test martin@merkaba:~/Zeit> cd find-Test martin@merkaba:~/Zeit/find-Test> ls martin@merkaba:~/Zeit/find-Test> mkdir dir martin@merkaba:~/Zeit/find-Test> touch file martin@merkaba:~/Zeit/find-Test> touch anotherfile martin@merkaba:~/Zeit/find-Test> find -type d -print -name "file" -printf "%s %p" -name "anotherfile" -print0 . ./dir ;) -- Martin 'Helios' Steigerwald - http://www.Lichtvoll.de GPG: 03B0 0D6C 0040 0710 4AFA B82F 991B EAAC A599 84C7 -- To UNSUBSCRIBE, email to debian-user-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org Archive: http://lists.debian.org/201208021959.09473.mar...@lichtvoll.de
Re: GNU find: "print0" and "-type" arguments
On Wed, Aug 01, 2012 at 09:12:49PM -0500, Alex Robbins wrote: > >Kumar > Yes, I read the man page and I know what the -print0 option is > supposed to do. Notice, however, that when I executed "find > -print0 -type d" the output (which, we both understand, is delimited > by null characters) includes the regular file, even though I > specified "-type d". My bad. Sorry for missing this. Kumar -- linux: because a PC is a terrible thing to waste (k...@cis.ufl.edu put this on Tshirts in '93) -- To UNSUBSCRIBE, email to debian-user-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org Archive: http://lists.debian.org/20120802115312.ga30...@bluemoon.alumni.iitm.ac.in
Re: GNU find: "print0" and "-type" arguments
Hi, Dňa Wed, 01 Aug 2012 19:33:35 -0500 Alex Robbins napísal: > I see (on a terminal screen that does not display null characters): > ../dir./file simple try to switch the arguments: find -type d -print0 ../dir The print0 and others are the "expressions" (see man find) and they must be at end of command. regards -- Slavko http://slavino.sk signature.asc Description: PGP signature
Re: GNU find: "print0" and "-type" arguments
Alex Robbins wrote: > I have a directory that looks like this: > . > ├── dir > └── file > "dir" is a directory and "file" is a regular file. I execute: > find -type d Here you are using the GNU find extension which allows the path to be omitted. In GNU find the path is optional. In the standard find the path must be specified. I always specify the path. It is portable. > and get the output: > . > ./dir Okay. > This is the expected output. However, when I execute: > find -print0 -type d It would be a lot cleaner to use -print for this example instead of -print0. I will use -print for illustrative purposes. But there isn't any difference between -print and -print0 for the issue you are talking about. > I see (on a terminal screen that does not display null characters): > ../dir./file You have the order of arguments backwards. You wanted to say this: find -type d -print That would do the right thing. Doing it the other way around doesn't make any sense. > The same goes for using "-type f". It appears as though find > ignores the -type argument when the -print0 option is passed. Isn't > this a bug? It is a bug in your usage. Arguments are evaluated from left to right across the command line. -print -- returns true, prints the full name -type X -- returns true if the type of file matches X So with this (bad) ordering: find . -print -type d # bad ordering You get this behavior: -print, prints the filename. All files are printed. -type d, returns true if the file is a directory. But nothing is after this on the command line so this value is a noop. That above bad ordering is exactly the same as: find . -print The other way around works as you intend it. find . -type d -print # good ordering -type d, returns true if the file is a directory. By returning true processing continues across the line. By returning false processing stops and the action skips to the next file. -print, prints the file name, returns true Does that help to make sense? Bob signature.asc Description: Digital signature
Re: GNU find: "print0" and "-type" arguments
Alex Robbins wrote: >I have a directory that looks like this: >. >├── dir >└── file >"dir" is a directory and "file" is a regular file. I execute: >find -type d >and get the output: >. >./dir >This is the expected output. However, when I execute: >find -print0 -type d >I see (on a terminal screen that does not display null characters): >../dir./file > >The same goes for using "-type f". It appears as though find ignores >the -type argument when the -print0 option is passed. Isn't this a >bug? > The -print or -print0 option needs to follow the selection criteria, such as -type. I'm pretty sure this is documented somewhere in the findutils manual. -- regards, kushal -- To UNSUBSCRIBE, email to debian-user-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org Archive: http://lists.debian.org/d416e2dc-c3f4-4361-a324-b5276366f...@email.android.com
Re: GNU find: "print0" and "-type" arguments
On 08/01/2012 08:41 PM, Kumar Appaiah wrote: On Wed, Aug 01, 2012 at 07:33:35PM -0500, Alex Robbins wrote: . ./dir This is the expected output. However, when I execute: find -print0 -type d I see (on a terminal screen that does not display null characters): ../dir./file The same goes for using "-type f". It appears as though find ignores the -type argument when the -print0 option is passed. Isn't this a bug? No. If you refer to the man page, it will reveal that -print0 actually outputs null characters instead of newlines. It is usually useful in conjunction with the -0 option for xargs to run commands on each file or directory found by find. Please read the man pages and they have nice examples at the bottom. Kumar Yes, I read the man page and I know what the -print0 option is supposed to do. Notice, however, that when I executed "find -print0 -type d" the output (which, we both understand, is delimited by null characters) includes the regular file, even though I specified "-type d". -- To UNSUBSCRIBE, email to debian-user-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org Archive: http://lists.debian.org/5019e221.80...@gmail.com
Re: GNU find: "print0" and "-type" arguments
On Wed, Aug 01, 2012 at 07:33:35PM -0500, Alex Robbins wrote: > . > ./dir > This is the expected output. However, when I execute: > find -print0 -type d > I see (on a terminal screen that does not display null characters): > ../dir./file > > The same goes for using "-type f". It appears as though find > ignores the -type argument when the -print0 option is passed. Isn't > this a bug? No. If you refer to the man page, it will reveal that -print0 actually outputs null characters instead of newlines. It is usually useful in conjunction with the -0 option for xargs to run commands on each file or directory found by find. Please read the man pages and they have nice examples at the bottom. Kumar -- Absolutely nothing should be concluded from these figures except that no conclusion can be drawn from them. -- Joseph L. Brothers, Linux/PowerPC Project) -- To UNSUBSCRIBE, email to debian-user-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org Archive: http://lists.debian.org/20120802014159.gb12...@bluemoon.alumni.iitm.ac.in
GNU find: "print0" and "-type" arguments
I have a directory that looks like this: . ├── dir └── file "dir" is a directory and "file" is a regular file. I execute: find -type d and get the output: . ./dir This is the expected output. However, when I execute: find -print0 -type d I see (on a terminal screen that does not display null characters): ../dir./file The same goes for using "-type f". It appears as though find ignores the -type argument when the -print0 option is passed. Isn't this a bug? -- To UNSUBSCRIBE, email to debian-user-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org Archive: http://lists.debian.org/5019cadf.8050...@gmail.com