1

Setup

I have a simple 1 line bash shell script. Its purpose, is to find all the files in a specific dir. Execute a curl POST of each file.. then move the files to a "old" dir.

Current attempt

Below is the find command I'm using.. I'm going to put it on multiple lines for easier reading, but it is all the same line in my script

sudo find . -type f 
-exec curl -vX POST -H "Content-Type: application/json" 
-H "Cache-Control: no-cache" -d @{} -u username:password 
"http://192.168.105.10/homeaccess/services/aCStats/uploadData?username=vangeeij&filename=$(basename {})" \; 
-exec sudo mv {} /home/vangeeij/acserver/resultsOld \;

Problem

Every part of the command works as desired except one part:

&filename=$(basename {})

I have tried every way I can think of to get the {} output from the find command to be placed directly after the equals sign and NOT have the leading ./ in front of the file name.

Earlier in the command -d @{} I need the ./ But here I don't

Previously Tried and failed

filename=$(basename {})
filename=$('echo {} | sed "s|^\./||"')

honestly the list goes on and on...

Question

In the exact usage above, how can I append the file name, minus the leading ./ directly after the filename= in the URL

DarbyM
  • 1,173
  • 2
  • 9
  • 25

2 Answers2

2

I suggest changing your find and curl to this simple loop in bash:

while IFS= read -d '' -r file; do
   base=$(basename "$file")
   curl -vX POST -H "Content-Type: application/json" -H "Cache-Control: no-cache" \
      -d @"$file" -u username:password \
      "http://192.168.105.10/homeaccess/services/aCStats/uploadData?username=vangeeij&filename=$base"
   sudo mv "$file" /home/vangeeij/acserver/resultsOld
done < <(sudo find . -type f -print0)

We are using process substitution here in a while/done loop to get these benefits:

  1. It will handle files with white spaces / glob characters due to use of -print0 and while IFS= read -d '' -r file
  2. It will avoid subshell creation for every file as the case with code in question
anubhava
  • 761,203
  • 64
  • 569
  • 643
  • 1
    This did the trick... I also preferred to keep the mv command in tact. Though I was hoping to pull it off with a single find command.. this solution is easier to read. – DarbyM Mar 11 '17 at 20:13
1

Consider using bash -c to execute your commands:

find . -type f -exec bash -c \
'curl -vX POST -H "Content-Type: application/json" \
-H "Cache-Control: no-cache" -d @{} -u username:password \
"http://192.168.105.10/homeaccess/services/aCStats/uploadData?username=vangeeij&filename=${1##*/} " \
-o /home/vangeeij/acserver/resultsOld/${1##*/}' _ {} \;

or as a one liner:

find . -type f -exec bash -c 'curl -vX POST -H "Content-Type: application/json" -H "Cache-Control: no-cache" -d @{} -u username:password "http://192.168.105.10/homeaccess/services/aCStats/uploadData?username=vangeeij&filename=${1##*/} " -o /home/vangeeij/acserver/resultsOld/${1##*/}' _ {} \;

The file names can then be handled as positional parameters and you can use Bash parameter expansion instead of basename.

You can avoid the use of mv by using the -o(output) flag in your curl.

More on this technique on Greg's wiki.

SLePort
  • 15,211
  • 3
  • 34
  • 44