I am trying to find (and store to a variable) the path of a file that is stored on another server by running the following command in one of my functions (included in .bashrc):

FILE_PATH=$(ssh -T user@host 'find <directory> -name *<filename>*')

However this is not returning any output. I have checked that there should be a file in the location that is grabbed, and I have also been able to replicate the command and store output to variable on the command line, but it does not work when running the function.

Does anyone know what's going on and why the command isn't working?


Here is a representation of what I am seeing:

function get_path {
    FILE_PATH=$(ssh -T user@hostB 'find /home/daverbuj -name *${FILE}*')
    echo "Here is the file: ${FILE_PATH}"
[daverbuj@hostA]$ FILE_A=$(ssh -T user@hostB 'find /home/daverbuj -name foo.bar')
[daverbuj@hostA]$ echo $FILE_A

[daverbuj@hostA]$ get_path foo.bar
Here is the file:

I am seeing what I expect when I run from the command line, but not when I run the function.

  • Edited. Both servers are RedHat v7.7. The function is in my .bashrc which is sourced every time I edit it. I am suspecting maybe having it in .bashrc is an issue and will try to make it as a standalone script.
    – Daverbuj
    Feb 3, 2022 at 22:42
  • The issue with .bashrc would be that the file isn't sourced when you ssh, or in various other cases, so that would just make the function error with a command not found. I doubt it would make a difference otherwise. Can you show the exact function? I doubt you're looking for a file named foo.bar, right? Is the find command a bit more complex in reality? There may also be quoting issues that will affect if you are passing the variable or the variable's contents, so if you can show the exact thing that would help at least rule some issues out.
    – terdon
    Feb 3, 2022 at 22:44
  • The full command is: ssh -T daverbuj@host 'find /xxxxx/prod_archive/research/xxxx/xxxx/xxxxx -maxdepth 3 -nowarn -name *xxxxx*region-2_cov_report.bed' 2>/dev/null Again, the weird part is that when I run this by itself I get output as expected. Running this from the function in bashrc returns nothing.
    – Daverbuj
    Feb 3, 2022 at 22:53
  • OK, please add that to your question but make sure you get the quoting exactly as you have it. Specifically, whether the name of the bed file is quoted or not since that could explain what's happening (if you don't quote it, the * will be expanded before the find command is run so it will work if you have a file matching the glob in your current directory). Also try without the 2>/dev/null in case you get any useful error.
    – terdon
    Feb 3, 2022 at 22:59
  • Yup that was it! I changed the single quotes to double quotes in that find command. Thanks so much for your help! Adding that part to my original question.
    – Daverbuj
    Feb 3, 2022 at 23:41

2 Answers 2

get_path() {
  local name=$1
  readarray -td '' reply < <(
    LC_FILE_NAME=$name ssh -o SendEnv=LC_FILE_NAME -n -T user@hostB '
      LC_ALL=C find /home/daverbuj -name "*$LC_FILE_NAME*" -print0')
  (( ${#reply[@]} )) &&
    echo "File path${reply[2]+s} with that name:" &&
    printf ' - %s\n' "${reply[@]}"
  • no need to use the ksh style of function definition (function f {...}), bash supports the standard f() compound-command as well.
  • there could be more than one matching file. To separate them out reliably, you need to use NUL as delimiter (-print0). bash variables can't hold NULs, but since version 4.4, its readarray builtin can split a NUL delimited input stream into elements of an array with -d ''.
  • * is a glob operator, so it needs to be quoted for both the local shell and remote shell so it be passed literally to find for it's -name name pattern matching operator.
  • You don't want to have the local shell expand a variable into the code passed to the remote shell as that would constitute some form of arbitrary command injection vulnerability, instead here, we've passing the $name value to the remote shell via a LC_FILE_NAME environment variable (assumes sshd on the remote host is configured with AcceptEnv LC_* which is common). In your code, you had the remote shell expand a $FILE variable (though had forgotten to quote it as well as the *), but you hadn't passed that variable from the local shell to the remote shell.
  • $REPLY for scalar and $reply for array is a common convention for a variable name where we return a result to the caller.
  • You can't use echo for arbitrary data (for data that you can't guarantee won't contain backslashes or start with -).
  • -name '*foo*' could fail to match all files with foo in their name in locales using multi-byte charsets such as UTF-8, as failure to decoding the file names into that charset would trip the fnmatch() used by find's -name. Hence the LC_ALL=C to fix to a single-byte locale.
  • here, we're returning a failure exit status unless at least one file was found and it was printed properly.
  • We're using the -n option of ssh to avoid it consuming input from stdin. You may also want to add a -o BatchMode=yes for more tuning relevant to processing meant to be unattended.

More reading on those here:


You can reroute stderr to stdout using

OUT=$(ssh -tt -vv [email protected] "remote command" 2>&1 )

you can edit something like this in your function and it should work!


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .