2

I have a shell command with the following format:

my_cmd -I file1.inp -O file1.out

Where some processing is done on file1.inp and the results are stored in file1.out

In my main directory, I have many files with the format: *.inp and I would like to run this command for all of them and the store the results to *.out. Can I only use shell script to achieve this?

1
  • 1
    sounded like an average question, but generated a lot of good answers, so I guess the question was good after all :) Commented Nov 3, 2016 at 14:46

3 Answers 3

5

You can use a simple loop:

for file in *.inp ; do
    my_cmd -I "${file}" -O "${file%%.inp}.out"
done

${file%%.inp} is a so called parameter expansion. It will effectively remove the extension .inp from the input filename.


One thing (thanks Jean-François Fabre). If the folder does not contain any .inp files the above loop would run once with $file having the literal value *.inp. To avoid that you need to set the nullglob option:

shopt -s nullglob # set the nullglob option
for file in *.inp ; do
    my_cmd -I "${file}" -O "${file%%.inp}.out"
done
shopt -u nullglob # unset the nullglob option
Sign up to request clarification or add additional context in comments.

7 Comments

I would add a test to see if $file is a file. 1) it could be a directory, 2) if there are no .inp files in the directory it calls the command with *.inp
An answer should focus on the problem asked by the OP. What you suggested might(!) be worth to implement for the OP but it is off-topic in my answer.
@Jean-FrançoisFabre You are right about the second point. Good catch!
Note that this last behavior can also be avoided by setting the shell option nullglob : after shopt -s nullglob, the *.inp will resolve to the empty string, avoiding the loop body from being executed.
@motam79 you can fork your instructions by using the & symbol. In your for loop, you could write my_cmd -I "${file}" -O "${file%%.inp}.out" &
|
4

Using GNU parallel

parallel my_cmd -I {} -O {.}.out ::: *.inp

By default, this will jobs in parallel, one job per core. {} is an unchanged argument, {.} is the same argument minus its extension. The arguments are taken from the words that follow :::.

Comments

-3
ls *.inp| xargs -l1 -I % my_cmd -I % -O %.out

6 Comments

@Aaron No, it can't. That's (for example) because ls will modify filenames as soon as they contain problematic letters. find won't do that. Don't parse the results of ls. Period.
I agree but I'm confused now. Please check your comment. Is it a typo?
Well I still understand myself, but I'm not a native english speaker so I may very well have written gibberish. I can't edit the comment anymore so I've deleted it and wrote another one
You can generally replace an unsafe ls | xargs by a safer find -exec
While these commands may solve the problem, it doesn't explain why or how they answer the question. Please include an explanation for your commands, as that really helps to improve the quality of your post. Flaggers / reviewers: For command-only answers such as this one, downvote, don't delete! (The same goes for incorrect answers.)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.