0

I have a command that should be executed by a shell script.

Actually the command does not matter the only thing that is important the further command execution and the right escaping of the critical parts.

The command that usually is executed normally in putty is something like this(maybe some additional flags for ls)

rm -r `ls /test/parse_first/ | awk '{print $2}' | grep trash`

but now I have a batch of such command so I would like to execute them in a loop

like

for i in {0..100}
 do
    str=str$i
    ${!str}
 done

where str is :

str0="rm -r `ls /test/parse_first/ | awk '{print $2}' | grep trash`"
str1="rm -r `ls /test/parse_second/ | awk '{print $2}' | grep trash`"

and that gives me a lot of headache cause the execution done by ${!str} brakes the quotations and inline shell between `...` marks

6
  • 4
    First, it's a bad idea to parse the output of ls. Can you describe the set of files that you want to delete? It looks like you are deleting files with the word trash in the file name. Commented Sep 19, 2013 at 20:36
  • 1
    I'm not sure why you refer to $2 from the output of ls. Commented Sep 19, 2013 at 20:39
  • cause the output of ls has some rows with two columns where the second one holds the name and the first the timestamp as I said ls should have some flags Commented Sep 19, 2013 at 20:59
  • 3
    You should absolutely read mywiki.wooledge.org/BashFAQ/050 aka "I'm trying to put a command in a variable, but the complex cases always fail!" Commented Sep 19, 2013 at 21:31
  • Provide Short, Self Contained, Correct Example or keep whining on every answer that it is not what you are thinking. Your choice. Commented Sep 19, 2013 at 22:18

4 Answers 4

1
my_rm() { rm -r `ls /test/$1 | awk ... | grep ... `; }
for i in `whatevr`; do
    my_rm $i
done;
Sign up to request clarification or add additional context in comments.

3 Comments

No wrapping in a function is not an option cause the commands will be different. But thanks any way.
then fix your question. I bet you can still apply the principle of my answer.
yep there is a point in using function wrapping but for now I want to try with string evaluation cause it involves a smaller amount of efort to change the source
0

Getting this right is surprisingly tricky, but it can be done:

for i in $(seq 0 100)
do
  str=str$i
  eval "eval \"\$$str\""
done

1 Comment

Thank you actually only this solution fits my needs. Only minor modifications I made to my commands(I've escaped the ` and some $ to avoid the first eval).Thanks a lot.
0

You can also do:

for i in {0..10}
do
    <whatevercommand>
done

2 Comments

looping is not a problem the Main thing is how to dynamically execute a command(by command i mean a long command with params inline shell executions and parameters like the ones in the post descrioption) that is stored in a variable
@JohnRobPeter Did you try my answer? I tested it with setup like yours (with rm changed to touch) and it worked as expected.
0

It's actually simpler to place them on arrays and use glob patterns:

#!/bin/bash

shopt -s nullglob

DIRS=("/test/parse_first/" "/test/parse_second/")

for D in "${DIRS[@]}"; do
    for T in "$D"/*trash*; do
        rm -r -- "$T"
    done
done

And if rm could accept multiple arguments, you don't need to have an extra loop:

for D in "${DIRS[@]}"; do
    rm -r -- "$D"/*trash*
done

UPDATE:

#!/bin/bash

readarray -t COMMANDS <<'EOF'
rm -r `ls /test/parse_first/ | awk '{print $2}' | grep trash
rm -r `ls /test/parse_second/ | awk '{print $2}' | grep trash
EOF

for C in "${COMMANDS[@]}"; do
    eval "$C"
done

Or you could just read commands from another file:

readarray -t COMMANDS < somefile.txt

5 Comments

this approach is bounded to rm command but I need a more generic one that would execute any command given by a var
@JohnRobPeter Please see update. And that's the most generic form you can have. Commands can never really be stored on a variable and executed in a safe manner. At least in a truly generic way.
I wish you'd show how to change awk '{print $2}' | grep trash to awk '$2 ~ /trash/ { print $2 }'.
@tripleee That's not what he's really after actually. And parsing arguments through word splitting is never a safe way. That should have been obvious to you already.
Just a random Useless Use of Grep reaction.

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.