Search code examples
linuxbashxargscp

xargs copy if file exists


I got a string with filenames I want to copy. However, only some of these files exist. My current script looks like this:

echo $x | xargs -n 1 test -f {} && cp --target-directory=../folder/ --parents

However, I always get a test: {}: binary operator expected error.

How can I do that?


Solution

  • You need to supply the -i flag to xargs for it to substitute {} for the filename.

    However, you seem to expect xargs to feed into the cp, which it does not do. Maybe try something like

    echo "$x" |
    xargs -i sh -c 'test -f {} && cp --target-directory=../folder/ --parents {}'
    

    (Notice also the use of double quotes with echo. There are very few situations where you want a bare unquoted variable interpolation.)

    To pass in many files at once, you can use a for loop in the sh -c:

    echo "$x" |
    xargs sh -c 'for f; do
        test -f "$f" && continue
        echo "$f"
    done' _ |
    xargs cp --parents --target-directory=".,/folder/"
    

    The _ argument is because the first argument to sh -c is used to populate $0, not $@