23

I want to run a simple for loop command with sudo, but it isn't working:

sudo -i -u user for i in /dir; do echo $i; done

I get the following error:

-bash: syntax error near unexpected token `do'

Probably a very simple thing I am overlooking. Any help?

Axl
  • 427
  • 2
  • 7
  • 19

3 Answers3

36

sudo wants a program (+arguments) as a parameter, not a piece of shell script. You can do this, though:

sudo -i -u user sh -c 'for i in /dir; do echo $i; done'

Note the single quotes. If you used double quotes, your shell would try to expand the $i before sudo (or, rather, the shell run by it) ever sees it.

PS. a separate problem, as pointed out in a comment (only six years later), is that if you want to iterate over the files in a directory, the proper syntax is for i in /dir/*. for accepts a list, and /dir is a list... with one item. /dir/* expands to a list of files in /dir due to wildcard expansion.

Jan Krüger
  • 17,870
  • 3
  • 59
  • 51
  • you got it! Good luck to all. – shellter Jun 04 '12 at 22:13
  • According to this, every output file will be written/saved in the home directory of the specified user. What if I want the output to be written in a specific one? – Alessandro Cuttin Dec 31 '13 at 11:39
  • @AlessandroCuttin the example doesn't write any output files. Seems like your comment is about an unspecified variation on the question...? – Jan Krüger Jan 06 '14 at 12:48
  • 1
    using back-quotes sudo -i -u root sh -c 'for i in /dir; do echo $i; done' gives me: sh: /dir: Is a directory Using single quotes returns nothing ... (Redhat) – user1767316 Sep 18 '18 at 14:39
  • @user1767316 I can't believe nobody noticed this before. I've added a note to the post. Thanks for your comment pointing this out! – Jan Krüger Sep 20 '18 at 08:35
  • Using this: `sudo -i -u user sh -c 'for i in /sys/bus/usb/devices/*/power/autosuspend; do echo -1 > $i; done'` I get a syntax error saying `Syntax error: ";" unexpected`. What am I doing wrong? – Max Feb 07 '20 at 14:20
  • @Max this works fine for me; tested with dash, bash and zsh. I think either something is messing up your command (if you haven't been typing it directly into a shell), or your `/bin/sh` is an alias for some other shell... – Jan Krüger Feb 11 '20 at 12:53
  • I had to remove the `-i` flag to run a python script as an other user, otherwise it was not able to find the `script.py` file in the loop. – swiss_knight Feb 11 '20 at 15:25
  • @JanKrüger Thanks for checking this again for me. Anyway, my shell is definitely a bash shell. I checked with `ps -p $$`. I decided to put the commands in a bash-script now and then execute the script as `sudo` – Max Feb 12 '20 at 09:16
  • Unfortunately, it works, but not as expected/desired Namely, [someuser ~]$ sudo -s /bin/sh -c -E 'for i in a b c* ; do echo $i; done' [someuser ~]$ instead of [someuser ~]$ for i in a b c ; do echo $i; done a b c [someuser ~]$ – al0 Nov 11 '21 at 15:50
7

You can try sudo bash -c 'commands here'

BLaZuRE
  • 2,356
  • 2
  • 26
  • 43
2

Put the sudo inside the loop:

for i in /dir; do
    sudo -u user somecommand $i
done

This won't work without extra steps if you need the other user's permissions to generate the glob for the loop, for example.

evil otto
  • 10,348
  • 25
  • 38
  • 5
    The problem with this is that if the sudo timeout is not big enough, it will ask for the password all the time :( – Lilás Dec 19 '16 at 19:07
  • I think this answer is not complete, and if you want to access/read files at "dir", you need sudo beforehand, so vote down...sorry! – jcoder8 Jun 08 '22 at 13:02