简体   繁体   中英

remove files via ssh and xargs

I am trying to remove files via ssh using by find and xargs. On the local machine command works correctly. I am using exception list also.

I have tried to changes brackets between ' ' and " " but it does not work.

save_files=(test1 test2)

On the local machine:

find / -mindepth 1 | grep -vE "$(IFS=\| && echo "${save_files[*]}")" | xargs rm -rf

via ssh:

su - user -c "ssh host find / -mindepth 1 | grep -vE '$(IFS=\| && echo "${save_files[*]}")' | xargs rm -rf"

In above ssh command xargs is performing locally. I need xargs on remote machine. Even I put find command in '' brackets like below:

su - user -c "ssh host 'find / -mindepth 1 | grep -vE '$(IFS=\| && echo "${save_files[*]}")' | xargs rm -rf'"

Can you try this?

su - user -c "ssh host 'save_files=test; find / -mindepth 1 | grep -vE "$save_files" | xargs rm -rf'"

Or after switching as root user try below one?

ssh host 'save_files=test; find / -mindepth 1 | grep -vE "$save_files" | xargs rm -rf'

The code for executing the command on a remote host:

su - user -c "ssh host 'find / -mindepth 1 | grep -vE '$(IFS=\| && echo "${save_files[*]}")' | xargs rm -rf'"

Is using double quote to pass the command to 'su -c', and then single quotes to pass the command to 'ssh' (which contain double quotes). However, the quoting does not support nesting, so that the quote in '$(IFS=... ... )' actually terminate the quote in 'find'.

You can execute the same with a 'set -vx' prefix, to see the expansion

su - owner -c "set -vx ; ssh localhost ...

and you will see

++ IFS='|'
++ echo 'test1|test2'
+ su - owner -c 'set -vx ; ssh localhost '\''set -x ; find /foo -mindepth 1 | grep -vE '\''test1|test2'\'' | xargs rm -rf'\'''
Password: 
+ ssh localhost 'set -x ; find /foo -mindepth 1 | grep -vE test1'
+ 'test2 | xargs rm -rf'
-su: test2 | xargs rm -rf: command not found
+ find /foo -mindepth 1
+ grep -vE test1
find: ‘/foo’: No such file or directory

Proposed Solution:

I was not able to find a way to get three level quoting (very frustrating) Possible solution may be to create a helper script h.sh, which will perform the 'ssh' command, and then invoking the helper script with 'su - user '/path/to/helper.sh'

Starting another answer, trying again for one-liner, avoiding the intermediate script.

The key problem is the three level quoting, whereas shell support only two level quoting (double quote, single quote). I believe it might be possible to eliminate the need for the 3rd level of quoting by using backquote in the pattern, eliminating the need to put it into quotes.

IFS=\| P="${save_files[*]}"   su - owner -c "ssh localhost 'set -vx ; find /tmp/xyz -mindepth 1 | grep -vE ${P//|/\\|} | xargs rm -rf'"

The solution create the pattern with 'escapes' - see '($P/|/\|}', eliminating the need to quote the pattern. Should work if the save_files does not have magic characters.

Notes:

  1. Notice that I've replaced '/' with /tmp/xyz, to reduce the change the accidental copy/paste will remove important data (already happen on my VM:-( ).
  2. The 'set -vx' is for debugging & troubleshooting, and can be removed

First connect your Remote system and run the bash command whatever you need, like find and xargs

ssh root@MachineB 'bash command'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM