LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices


Reply
  Search this Thread
Old 05-13-2011, 08:04 AM   #1
linuxbird
Member
 
Registered: Feb 2006
Distribution: Slackware
Posts: 543

Rep: Reputation: 36
Script question with find -exec


I am trying to check flac files in a multi-level directory structure, and would ideally like to get ordered output with the full path file name.

I could write a multiline script, but was wondering if there were better ways of accomplishing this.

The current command I am using is:

Code:
find . -name '*flac' -exec flac -t {} \;
 
Old 05-13-2011, 08:23 AM   #2
szboardstretcher
Senior Member
 
Registered: Aug 2006
Location: Detroit, MI
Distribution: GNU/Linux systemd
Posts: 4,278

Rep: Reputation: 1694Reputation: 1694Reputation: 1694Reputation: 1694Reputation: 1694Reputation: 1694Reputation: 1694Reputation: 1694Reputation: 1694Reputation: 1694Reputation: 1694
"ordered output with the full path file name"

What does that mean? Where do you want this output from? Could you provide an example of what you are getting, and what you would like?
 
Old 05-13-2011, 08:43 AM   #3
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852

Rep: Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037
What do you mean exactly by "ordered output"? What do you mean by "full path file name" (those terms don't quite go together). Give us an actual example of what kind of results you want, and we'll try to help you.

As a first step though, find by default outputs file names appended with the input search path you feed it. So if you use "find ." you'll get output formatted as "./file". If you use "find /full/path/to" then your output will be "/full/path/to/file".

Also, instead of running the command directly, you could create a separate script that does the actual processing, including formatting the filenames, and call that with -exec.
 
Old 05-13-2011, 09:05 AM   #4
PTrenholme
Senior Member
 
Registered: Dec 2004
Location: Olympia, WA, USA
Distribution: Fedora, (K)Ubuntu
Posts: 4,187

Rep: Reputation: 354Reputation: 354Reputation: 354Reputation: 354
You could try something like this:
Code:
$!/bin/bash
find . -name '*flac' -exec flac -t '{}' ';' | while readline path;do base=$(basename ${path});sorted[${basename}]="${path}";done;for p in "$path[@]";do echo "${path[${p}]};done
Note: Untested code - I'm on an old XP system right now, defraging a large disk for my sister.
 
Old 05-13-2011, 12:25 PM   #5
linuxbird
Member
 
Registered: Feb 2006
Distribution: Slackware
Posts: 543

Original Poster
Rep: Reputation: 36
Thanks everyone. Ideally I would like something like:


./file/path/track.flac <then the flac -t option output>

I'm not real picky, I would just like to do hundreds of files, and then scan through the list for defects.

In terms of order, I guess I would like to do something akin to a:

find . | grep '.flac' | sort | exec {something}

But I am not sure that I really understand the use of exec outside the find command.

And for getting the file name printed I was thinking I could use a tee command after the sort, before the exec.

So I'm kind fishing for guidance and ideas. Thanks everyone!
 
Old 05-13-2011, 07:08 PM   #6
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852

Rep: Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037
"-exec" is just what it says on the tin. Execute the specified command for each matching file, with "{}" being where the file name goes.

However it's really only designed for simple, one-shot style operations. If you have a series of complex commands to run then it's usually better to write up a shell script of some kind, and only use find to produce the list of files for it to operate on.

Edit: There other exec commands out there, such as the bash built-in command, but those are completely different beasts. Don't confuse them with the find option.

Last edited by David the H.; 05-13-2011 at 07:10 PM.
 
Old 05-13-2011, 10:40 PM   #7
AnanthaP
Member
 
Registered: Jul 2004
Location: Chennai, India
Posts: 952

Rep: Reputation: 217Reputation: 217Reputation: 217
find . -name "*flac" -print | sort
should sort by directory path.

find . -name "*flac" -print | awk '{print $NF, $0}' | sort
should sort by file name first.

OK
 
Old 05-14-2011, 01:23 PM   #8
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852

Rep: Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037
Code:
find . -name "*flac" -print | awk '{print $NF, $0}' | sort
But this has a side effect of awk printing the filename twice, which wouldn't be good if you're trying to pipe the output into further commands. Also, I think you forgot to change the field separator to "/".


One common way to process sorted input is to use xargs to execute the commands, instead of -exec.
Code:
find . -name "*flac" -print0 | sort -hz | xargs -0 flac -t
The -print0 option in find separates the output by null characters instead of newlines, which makes it possible to easily handle files with spaces or other reserved characters, and sort's -z and xargs -0 options tell them to process the null-terminated input. Whether you need this or not depends on what kind of filenames you have.

Finally, I added the -h human-numeric-sort option to sort, so that 10 will come after 9 instead of after 1.

As for the full-path-in-the-output thing, I see now that the problem is actually with flac. It only displays the filename when printing the results of -t. There appears to be nothing we can do with find or anything else that can affect that.

The only thing I can think of then is to set up a script to check the test results.
Code:
#!/bin/bash

while read file ; do

     flac --totally-silent -t "$file"

     if (( $? == 0 )); then
          echo "valid: $file"
     else
          echo "not valid: $file"
     fi

done  < <( find "$1" -name "*.flac" -print | sort -h )

exit 0
Launch it as "scriptname startdir".

So basically I've turned off flac's default output and instead print valid or invalid depending on the exit code of the test. According to the man page, the exit code will be 0 if the file is valid, and 1 if not. I'm assuming here that you won't need to worry so much about the full path if you can easily spot the bad files in the output, but if you still want to see it, just make sure the starting input contains the full path to the input.

Last edited by David the H.; 05-14-2011 at 01:27 PM. Reason: minor rewording
 
1 members found this post helpful.
Old 05-14-2011, 11:31 PM   #9
AnanthaP
Member
 
Registered: Jul 2004
Location: Chennai, India
Posts: 952

Rep: Reputation: 217Reputation: 217Reputation: 217
Quote:
Code:
find . -name "*flac" -print | awk '{print $NF, $0}' | sort
But this has a side effect of awk printing the filename twice, which wouldn't be good if you're trying to pipe the output into further commands. Also, I think you forgot to change the field separator to "/".
Actually, putting $NF first means that I need not worry about the field separator.

But what I wanted to discuss was single-quotes (in the OP's use of '*flac' .v. "*flac" .

OK
 
Old 05-15-2011, 12:34 AM   #10
Tinkster
Moderator
 
Registered: Apr 2002
Location: earth
Distribution: slackware by choice, others too :} ... android.
Posts: 23,067
Blog Entries: 11

Rep: Reputation: 928Reputation: 928Reputation: 928Reputation: 928Reputation: 928Reputation: 928Reputation: 928Reputation: 928
Quote:
Originally Posted by AnanthaP View Post
Actually, putting $NF first means that I need not worry about the field separator.

But what I wanted to discuss was single-quotes (in the OP's use of '*flac' .v. "*flac" .

OK


Ummm ... no. Unless he has lots of filenames with spaces/tabs in them all you
get is the same file printed twice on the same line, because then $NF==1. And
w/ only one field $1 and $0 are the same thing. Now I'm not suggesting that
printing $NF for files w/ spaces should be considered meaningful for sorting... ;D



Cheers,
Tink
 
Old 05-15-2011, 12:36 AM   #11
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208
David the H's suggestion could be coded as
Code:
#!/bin/bash

while read file ; do

     flac --totally-silent -t "$file" && echo "valid: $file" || echo "not valid: $file"

done  < <( find "$1" -name "*.flac" -print | sort -h )

exit 0
 
1 members found this post helpful.
Old 05-15-2011, 03:04 AM   #12
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852

Rep: Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037
Yes, it can be done that way, but I like to avoid the x && y || z pattern most of the time. I prefer the clarity to the conciseness.

There's also a potential pitfall you can avoid by not depending too much on that pattern:
http://mywiki.wooledge.org/BashPitfa...d2_.7C.7C_cmd3
 
Old 05-15-2011, 03:21 AM   #13
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852

Rep: Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037
@AnanthaP, if you want to sort by filename, you have to separate the name from the path. As Tinkster pointed out, if awk's field separator is the default, then each file path will be seen as a single word and the output will be "/path/to/filename /path/to/filename", which is pretty much meaningless.

Of course even if you do change the FS to"/", all you get is an output that looks like "/path/to/filename filename", which is equally useless further down the line.

Try it yourself if you don't believe me. I did.

But this makes me wonder, is it possible to tell sort to sort on the last field of the line, whatever the length? I don't think so, but I could be wrong.
 
  


Reply

Tags
find



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Find with -exec argument - not giving proper output..how to find... hinetvenkat Linux - Server 4 01-25-2010 06:19 AM
Shell Scripting Question (mv via find/-exec) ddenton Linux - General 3 11-21-2008 08:10 AM
find -exec syntax: bug in find? mfcarroll Programming 5 06-21-2007 07:13 PM
Assistance with 'find -exec cp' shell script dick.swift Linux - Software 6 01-23-2006 10:00 AM
find -exec question eantoranz Linux - General 1 06-26-2004 10:57 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie

All times are GMT -5. The time now is 03:00 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration