algorhythm
algorhythm

Reputation: 3426

Shell scipt: Find if a filename exists or not within a specific directory on another server

I have some pseduocode below and would like to know if it would work/ is the best method to tackle the problem before I begin developing the code.

I need to dynamically search through a directory on one server and find out if it exists on another server or not. The path will be different so I use basename and save it as a temporary variable.

for $FILE in $CURRENT_DIRECTORY
$TEMP=$(basename "$FILE" )

if [ssh user@other_serverip find . -name '$TEMP']; then
//write code here
fi

Would this if statement return true if the file existed on the other server?

Upvotes: 0

Views: 42

Answers (2)

Adam Katz
Adam Katz

Reputation: 16128

Here is a functioning, cleaner implementation of your logic:

for FILE in *; do

  if ssh user@other_serverip test -e "$FILE"; then
    # write code here
  fi

done

(There won't be a path on files when the code is composed this way, so you don't need basename.) test -e "$FILE" will silently exit 0 (true) if the file exists and 1 (false) if the file does not, though ssh will also exit with a false code if the connection fails.

However, that is a very expensive way to solve your issue. It will fail if your current directory has too many files in it and it runs ssh once per file.

You're better off getting a list of the remote files first and then checking against it:

#!/bin/sh

if [ "$1" != "--xargs" ]; then # this is an internal flag

  (
    ssh user@other_serverip find . -maxdepth 1           # remote file list
    find . -maxdepth 1                                   # local file list
  ) |awk '++seen[$0]==2' |xargs -d "\n" sh "$0" --xargs  # keep duplicates

else

  shift  # remove the --xargs marker
  for FILE in "$@"; do
    # write code here using "$FILE" (with quotes)
  done

fi

This does two things. First, since the internal --xargs is not given when you run the script, it connects to the remote server and gets a list of all files in the home directory there. These will be listed as ./.bashrc for example. Then the same list is generated locally, and the results are passed to awk.

The awk command builds an associative array (a hash) from each item it sees, incrementing it and then checking the total against the number two. It prints the second instance of any line it sees. Those are then passed on to xargs, which is instructed to use \n (a line break) as its delimiter rather than any space character.

Note: this code will break if you have any files that have a line break in their name. Don't do that.

xargs then recursively calls this script, resulting in the else clause and we loop through each file. If you have too many files, be aware that there may be more than one instance of this script (see man xargs).

 

This code requires GNU xargs. If you're on BSD or some other system that doesn't support xargs -d "\n", you can use perl -pe 's/\n/\0/' |xargs -0 instead.

Upvotes: 2

bipll
bipll

Reputation: 11940

It would return true if ssh exits successfully. Have you tried command substitution and parsing find's output instead?

Upvotes: 1

Related Questions