Modifying replace string in xargs

bash, xargs

Solution

In cases like this, a `while` loop would be more readable:

find . -name "*.txt" | while IFS= read -r pathname; do
    base=$(basename "$pathname"); name=${base%.*}; ext=${base##*.}
    mv "$pathname" "foo/${name}.bar.${ext}"
done

Note that you may find files with the same name in different subdirectories. Are you OK with duplicates being over-written by `mv`?

Problem

When I am using `xargs` sometimes I do not need to explicitly use the replacing string: ``` find . -name "*.txt" | xargs rm -rf ``` In other cases, I want to specify the replacing string in order to do things like: ``` find . -name "*.txt" | xargs -I '{}' mv '{}' /foo/'{}'.bar ``` The previous command would move all the text files under the current directory into `/foo` and it will append the extension `bar` to all the files. If instead of appending some text to the replace string, I wanted to modify that string such that I could insert some text between the name and extension of the files, how could I do that? For instance, let's say I want to do the same as in the previous example, but the files should be renamed/moved from `<name>.txt` to `/foo/<name>.bar.txt` (instead of `/foo/<name>.txt.bar`). UPDATE: I manage to find a solution: ``` find . -name "*.txt" | xargs -I{} \ sh -c 'base=$(basename $1) ; name=${base%.*} ; ext=${base##*.} ; \ mv "$1" "foo/${name}.bar.${ext}"' -- {} ``` But I wonder if there is a shorter/better solution.

Original source