[opensuse] 'find' and/or xargs experts, a hopefully simple syntax question
All,
In non-working-psuedo-find-language I want to find a command to do:
find . -name \*.E01 -exec ewfverify -l $(basename '{}').ewfverify.out '{}' ;
Can anyone give me the right syntax. I'm not sure if it is easier to
add xargs to the mix, if so that's fine too.
=== background with examples
I have common situation where I have a parent folder with multiple
children folders.
This command more or less does what I want:
find . -name \*.E01 | xargs -n 1 ewfverify > ewfverify.out
That effectively does the same as
(ewfverify
ewfverify.out
But I really want to have each command be more like:
ewfverify -l
Greg Freemyer wrote:
All,
In non-working-psuedo-find-language I want to find a command to do:
find . -name \*.E01 -exec ewfverify -l $(basename '{}').ewfverify.out '{}' ;
Can anyone give me the right syntax. I'm not sure if it is easier to add xargs to the mix, if so that's fine too.
=== background with examples
I have common situation where I have a parent folder with multiple children folders.
This command more or less does what I want:
find . -name \*.E01 | xargs -n 1 ewfverify > ewfverify.out
That effectively does the same as (ewfverify
;ewfverify ;ewfverify ;ewfverify ; etc ) ewfverify.out
But I really want to have each command be more like:
ewfverify -l
.ewfverify_log I think just using find -exec will be better.
Hi Greg your first exmaple will probably do what you want, you just need a couple of strategically placed escapes. I'm no fan of the -exec option, I would do this instead: find . -name \*.E01 -printf '%f %p\n' | \ xargs printf "ewfverify -l \$(basename %s).ewfverify.out %s\n" | sh /Per -- Per Jessen, Zürich (-4.6°C) http://www.dns24.ch/ - free DNS hosting, made in Switzerland. -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse+owner@opensuse.org
On 02/25/2013 07:35 PM, Greg Freemyer wrote:
In non-working-psuedo-find-language I want to find a command to do:
find . -name \*.E01 -exec ewfverify -l $(basename '{}').ewfverify.out '{}' ;
Hi Greg, if you can control the file names, i.e. that there are no "bad" ones with spaces or other unusual characters, then I'd use the shell: find . -name '*.E01' | while read F do ewfverify -l "$(basename $F).ewfverify.out" "$F" done Otherwise, you could use -execdir: $ find . -name '*.E01' -execdir ewfverify -l $(pwd)/'{}'.out '{}' \; But be aware that input files with the same basename will owerwrite each others .out file (in both above variants), as it they all are written in the current (working) directory. Have fun, Berny -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse+owner@opensuse.org
Greg Freemyer said the following on 02/25/2013 01:35 PM:
All,
In non-working-psuedo-find-language I want to find a command to do:
find . -name \*.E01 -exec ewfverify -l $(basename '{}').ewfverify.out '{}' ;
I much prefer the use of sign;e quotes, e.g. '*.E01' But that's one of my ideosyncracies.
Can anyone give me the right syntax. I'm not sure if it is easier to add xargs to the mix, if so that's fine too.
There's a similar quoting issue with "-exec". <quote> All following arguments to find are taken to be arguments to the command until an argument consisting of `;' is encountered. The string `{}' is replaced by the current file name being processed everywhere it occurs in the arguments to the command, </quote> Where it says "The string '{}' ... Should that be single quoted when used or is that just in the context of the manual? Later, we find <quote> find . -type f -exec file '{}' \; Runs `file' on every file in or below the current directory. Notice that the braces are enclosed in single quote marks to protect them from interpretation as shell script punctuation. The semicolon is similarly protected by the use of a backslash, though single quotes could have been used in that case also. </quote> So if you are right to use '{}' on the command line then you missed out on the ';'
=== background with examples
I have common situation where I have a parent folder with multiple children folders.
This command more or less does what I want:
find . -name \*.E01 | xargs -n 1 ewfverify > ewfverify.out
I'd say "less" because you over-write the file on each iteration. Perhaps you mean ">>" instead of ">" You might also look at "-print0" and "-0"
I think just using find -exec will be better.
I disagree. I'm a firm believer in the old UNIX axiom "Each thing does one thing and only one thing and does it well" Rather than get myself confused I might even write it in this form find .... | while read filename do cd ........ ewverify $filename ...... done That way I'm sure about a lot of things, such as the directory the commands are being run in. -- ... it is easy to be blinded to the essential uselessness of them by the sense of achievement you get from getting them to work at all. In other words... their fundamental design flaws are completely hidden by their superficial design flaws. -- The Hitchhiker's Guide to the Galaxy, on the products of the Sirius Cybernetics Corporation. -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse+owner@opensuse.org
On Mon, Feb 25, 2013 at 2:34 PM, Anton Aylward
Greg Freemyer said the following on 02/25/2013 01:35 PM:
All,
In non-working-psuedo-find-language I want to find a command to do:
find . -name \*.E01 -exec ewfverify -l $(basename '{}').ewfverify.out '{}' ;
I much prefer the use of sign;e quotes, e.g. '*.E01' But that's one of my ideosyncracies.
Can anyone give me the right syntax. I'm not sure if it is easier to add xargs to the mix, if so that's fine too.
There's a similar quoting issue with "-exec". <quote> All following arguments to find are taken to be arguments to the command until an argument consisting of `;' is encountered. The string `{}' is replaced by the current file name being processed everywhere it occurs in the arguments to the command, </quote>
Where it says "The string '{}' ...
Should that be single quoted when used or is that just in the context of the manual?
Later, we find <quote> find . -type f -exec file '{}' \;
Runs `file' on every file in or below the current directory. Notice that the braces are enclosed in single quote marks to protect them from interpretation as shell script punctuation. The semicolon is similarly protected by the use of a backslash, though single quotes could have been used in that case also. </quote>
So if you are right to use '{}' on the command line then you missed out on the ';'
Damn, I was a lot closer than I thought. Adding a \ at the end should also work. I also left an arg off basename. This sounds like it should work: find . -name \*.E01 -exec ewfverify -l $(basename -s .E01 '{}').ewfverify.out '{}' \; The actual verifies takes a couple hours each, but if I try the above with a echo I still have one issue left, basename doesn't seem to work:
find . -name \*.E01 -exec echo ewfverify -l $(basename -s.E01 '{}').ewfverify.out '{}' \;
ewfverify -l ./dir1/image1.E01.ewfverify.out ./dir1/image1.E01 ewfverify -l ./dir2/image2.E01.ewfverify.out ./dir2/image2.E01 ewfverify -l ./dir3/image3.E01.ewfverify.out ./dir3/image3.E01 ewfverify -l ./dir4/image4.E01.ewfverify.out ./dir4/image4.E01 ewfverify -l ./dir5/image5.E01.ewfverify.out ./dir5/image5.E01 Basename is working in Per's example, so there is still something wrong above. For now, I will use Per's syntax.
=== background with examples
I have common situation where I have a parent folder with multiple children folders.
This command more or less does what I want:
find . -name \*.E01 | xargs -n 1 ewfverify > ewfverify.out
I'd say "less" because you over-write the file on each iteration. Perhaps you mean ">>" instead of ">"
No, the > redirects all of the output into a single concatenated file in this case. Think of it more like ( find . -name \*.E01 | xargs -n 1 ewfverify) > ewfverify.out But the () is implied in the original.
You might also look at "-print0" and "-0"
I'm familiar, but these are files I'm creating, so I won't be having spaces in the middle of the files. Thanks Greg -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse+owner@opensuse.org
On Mon, Feb 25, 2013 at 2:21 PM, Per Jessen
Greg Freemyer wrote:
All,
In non-working-psuedo-find-language I want to find a command to do:
find . -name \*.E01 -exec ewfverify -l $(basename '{}').ewfverify.out '{}' ;
Can anyone give me the right syntax. I'm not sure if it is easier to add xargs to the mix, if so that's fine too.
=== background with examples
I have common situation where I have a parent folder with multiple children folders.
This command more or less does what I want:
find . -name \*.E01 | xargs -n 1 ewfverify > ewfverify.out
That effectively does the same as (ewfverify
;ewfverify ;ewfverify ;ewfverify ; etc ) ewfverify.out
But I really want to have each command be more like:
ewfverify -l
.ewfverify_log I think just using find -exec will be better.
Hi Greg
your first exmaple will probably do what you want, you just need a couple of strategically placed escapes. I'm no fan of the -exec option, I would do this instead:
find . -name \*.E01 -printf '%f %p\n' | \ xargs printf "ewfverify -l \$(basename %s).ewfverify.out %s\n" | sh
Per, You almost read my mind. Adding a -s .E01 gives me what I really wanted. find . -name \*.E01 -printf '%f %p\n' | \ xargs printf "ewfverify -l \$(basename -s .E01 %s).ewfverify.out %s\n" | sh Thanks Greg -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse+owner@opensuse.org
On Mon, Feb 25, 2013 at 2:22 PM, Bernhard Voelker
On 02/25/2013 07:35 PM, Greg Freemyer wrote:
In non-working-psuedo-find-language I want to find a command to do:
find . -name \*.E01 -exec ewfverify -l $(basename '{}').ewfverify.out '{}' ;
Hi Greg,
if you can control the file names, i.e. that there are no "bad" ones with spaces or other unusual characters, then I'd use the shell:
find . -name '*.E01' | while read F do ewfverify -l "$(basename $F).ewfverify.out" "$F" done
Otherwise, you could use -execdir:
$ find . -name '*.E01' -execdir ewfverify -l $(pwd)/'{}'.out '{}' \;
But be aware that input files with the same basename will owerwrite each others .out file (in both above variants), as it they all are written in the current (working) directory.
Have fun, Berny
2 more good solutions. Both seem to work fine. And yes, my filenames are guaranteed unique, otherwise I would dump the verify log in the directory with the image. Thanks Greg -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse+owner@opensuse.org
Hello, On Mon, 25 Feb 2013, Greg Freemyer wrote:
In non-working-psuedo-find-language I want to find a command to do:
find . -name \*.E01 -exec ewfverify -l $(basename '{}').ewfverify.out '{}' ;
Can anyone give me the right syntax. I'm not sure if it is easier to add xargs to the mix, if so that's fine too.
The "canonical" "right" way is like this: find . -name '*.E01' -exec bash -c ' ewfverify -l "$(basename "$1").ewfverify.out" "$1" ' find-bash -- '{}' ';' The syntax behind the -exec is: /bin/bash # shell to call, here 'sh' # other shell option[s], here none -c 'script' # option '-c' + script find-bash # argument $0 for the script, you'll see # that 'find-bash' in a 'ps' output -- # end of sh-options '{}' # argument[s] for the script after -c [;+] # end marker for find Alternatively one can use with BSD-find and newer GNU-find: find . -name '*.E01' -exec bash -c ' for file; do ewfverify -l "$(basename "$file").ewfverify.out" "$file" done ' find-bash -- '{}' '+' (assuming that starting the shell dominates the execution, if the work that'd go inside the for-file-loop dominates the work it's little relevant as seems to be in your case). Both above solutions are (mostly) portable and robust regarding filenames etc. as long as you write your script(-fragment) robust (and portable), i.e. above should not have problems with any legal filenames, e.g. linebreaks should not be any problem. Haven't tested it recently though. Instead of 'sh -c SCRIPT' you can use a saved script to ease quoting. -exec ewfverify-wrapper '{}' '+' with ewfverify-wrapper being in your PATH (e.g. ~/bin/) and containing: ==== ~/bin/ewfverify-wrapper ==== #!/bin/bash for file; do ewfverify -l "$(basename "$file").ewfverify.out" "$file" done ==== or whatever needs to be done. E.g. calling 'awk' or other stuff that one likes to use '' for quoting with from inside a 'sh -c' is extremely yucky, a sh -c 'awk -F '\''/'\'' '\''{printf("%s\n", $NF);}'\''' is just the start of it. HTH, -dnh -- Life sucks, and then you die. And then it still sucks. -- Georgia 'George' Lass, Dead Like Me -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse+owner@opensuse.org
David,
It is great to have the "canonical" "right" way to do it.
(I mean that, I am in the process of moving some work flows for my
office from Windows GUI apps to Linux CLI tools, so I want the result
to be as robust as I can get it.)
For me the script's speed is trivial. ie. Each ewfverify takes on the
order of hours to complete, so the number of 10's of second it
requires to launch is lost in the noise.
Greg
On Wed, Feb 27, 2013 at 12:39 AM, David Haller
Hello,
On Mon, 25 Feb 2013, Greg Freemyer wrote:
In non-working-psuedo-find-language I want to find a command to do:
find . -name \*.E01 -exec ewfverify -l $(basename '{}').ewfverify.out '{}' ;
Can anyone give me the right syntax. I'm not sure if it is easier to add xargs to the mix, if so that's fine too.
The "canonical" "right" way is like this:
find . -name '*.E01' -exec bash -c ' ewfverify -l "$(basename "$1").ewfverify.out" "$1" ' find-bash -- '{}' ';'
The syntax behind the -exec is: /bin/bash # shell to call, here 'sh' # other shell option[s], here none -c 'script' # option '-c' + script find-bash # argument $0 for the script, you'll see # that 'find-bash' in a 'ps' output -- # end of sh-options '{}' # argument[s] for the script after -c [;+] # end marker for find
Alternatively one can use with BSD-find and newer GNU-find:
find . -name '*.E01' -exec bash -c ' for file; do ewfverify -l "$(basename "$file").ewfverify.out" "$file" done ' find-bash -- '{}' '+'
(assuming that starting the shell dominates the execution, if the work that'd go inside the for-file-loop dominates the work it's little relevant as seems to be in your case).
Both above solutions are (mostly) portable and robust regarding filenames etc. as long as you write your script(-fragment) robust (and portable), i.e. above should not have problems with any legal filenames, e.g. linebreaks should not be any problem. Haven't tested it recently though.
Instead of 'sh -c SCRIPT' you can use a saved script to ease quoting.
-exec ewfverify-wrapper '{}' '+'
with ewfverify-wrapper being in your PATH (e.g. ~/bin/) and containing:
==== ~/bin/ewfverify-wrapper ==== #!/bin/bash for file; do ewfverify -l "$(basename "$file").ewfverify.out" "$file" done ====
or whatever needs to be done. E.g. calling 'awk' or other stuff that one likes to use '' for quoting with from inside a 'sh -c' is extremely yucky, a sh -c 'awk -F '\''/'\'' '\''{printf("%s\n", $NF);}'\''' is just the start of it.
HTH, -dnh
-- Life sucks, and then you die. And then it still sucks. -- Georgia 'George' Lass, Dead Like Me -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse+owner@opensuse.org
-- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse+owner@opensuse.org
participants (5)
-
Anton Aylward
-
Bernhard Voelker
-
David Haller
-
Greg Freemyer
-
Per Jessen