-1

I want to do the equivalent of:

for i in `ls -1`; do echo $i | mv $i `sed 's/profile/account/'`; done

with xargs

ls -1 | xargs -I{} mv {} `echo {} | sed 's/profile/account/'`

But the sed after the pipe within backticks is ignored. Anyone know why that's the case?

Edit: More info

The root problem is simply to rename files in a directly given a pattern replacement (here replace profile with account, however that is solved with for in loop over the files.

The question I'm posing is why is the following not working.

ls -1 | xargs -I{} mv {} `echo {} | sed 's/profile/account/'`

Why does the

`echo {} | sed 's/profile/account/'`

portion not return the replaced filename but the original filename. It's as if the | doesn't work inside the backticks.

To write the problem differently:

If I have a list like in a file called list.txt

profile1.txt
profile2.txt 

And want to generate

account1.txt
account2.txt 

While operating on each individual line separately so I can run a command on it.

cat list.txt | xargs -I{} echo `echo {} | sed 's/profile/account/'`

Why does command return:

profile1.txt
profile2.txt 

Instead of changing profile to account?

bucabay
  • 5,235
  • 2
  • 26
  • 37
  • Wrong quotes around `echo {} ...`? – arrowd Oct 21 '18 at 04:58
  • 1
    first of all, please [don't parse ls](https://mywiki.wooledge.org/ParsingLs).. use `for i in *`.. second, [put variables inside double quotes](https://unix.stackexchange.com/questions/131766/why-does-my-shell-script-choke-on-whitespace-or-other-special-characters) unless you have some other reason... finally, could you explain what is the problem you are trying to solve? ideally, give us one or two filenames and what is your expected output for those – Sundeep Oct 21 '18 at 05:02
  • you could use [parameter expansion](https://mywiki.wooledge.org/BashGuide/Parameters#Parameter_Expansion) directly on shell variables instead of calling `sed` (unless you need regex features) – Sundeep Oct 21 '18 at 05:04

3 Answers3

1

This might work for you (GNU parallel):

parallel 'old={}; new=${old/profile/account}; echo mv $old $new' ::: *

Remove echo once checked.

potong
  • 55,640
  • 6
  • 51
  • 83
0

Agree with the comments above regarding using shell glob expansion rather than ls -1, or the straightforward solution using prename, nevertheless the exercise is interesting also in case you wanted to feed the pipe other outputs (e.g. find or alike).

Below does it via calling a mini scriptlet where its argument is each xargs fed line, using var replacement bash-isms (note the narrowed ls ... to be able to re-run these without errors):

ls -1 *profile* | xargs -l1 bash -xc 'echo mv "$1" "${1/profile/account}"' --

Note above is a dry-run, remove the echo to actually do it.

jjo
  • 2,595
  • 1
  • 8
  • 16
0

In the example:

cat list.txt | xargs -I{} echo `echo {} | sed 's/profile/account/'`

xargs does not interpolate the {} inside of backticks.

So:

`echo {} | sed 's/profile/account/'`

Echos the literal {}. The subsequent sed does not change the {}.

`echo {} | sed 's/profile/account/'`

Will return: {}

Which gives:

cat list.txt | xargs -I{} echo {}
bucabay
  • 5,235
  • 2
  • 26
  • 37