1

Assume I have files named "*.data.done". Now I want to rename them (recursively) back to "*.data" then ones which contains "pattern"

So here we go:

grep -l -R -F "pattern" --include '*.data.done' * | xargs -I{} mv {} ${{}::-5}

Well, this stripping of '.done' is not working (bash 4.3.11):

bash: ${{}::-5}: bad substitution

How can I do this most easiest way?

robert
  • 1,921
  • 2
  • 17
  • 27
  • I'd create a tiny script: `for file in "$@"; do mv "$file" "${file%.done}"; done` in a file `moveit.sh` and then use `xargs sh moveit.sh`. It's simple, and cleaning up the `moveit.sh` file isn't a huge overhead. – Jonathan Leffler May 19 '16 at 14:24
  • `{}` isnt a shell variable, you can't do shell paramter expansion on it. – 123 May 19 '16 at 14:26

1 Answers1

3

Placeholder {} cannot be used in BASH's string manipulations inside ${...}.

You can use:

grep -lRF "pattern" --include '*.data.done' . |
xargs -I{} bash -c 'f="{}"; mv "$f" "${f/.done}"'

However if you want to avoid spawning subshell for each file then use a for loop:

while IFS= read -d '' -r f; do
    mv "$f" "${f/.done}"
done < <(grep -lRF "pattern" --include '*.data.done' --null .)
anubhava
  • 761,203
  • 64
  • 569
  • 643