Search code examples
bashsql-loaderinotifywait

Use inotifywait to change filename and further loop through sql loader


Objective: The moment multiple.csv files are uploaded to the folder, code should check each filename, if appropriate filename, file should be further used by sqlloader to get data uploaded in the database. Once file is uploaded, code should delete the file processed. Next time, same process repeats.

I have some parts of the code working but some are creating problem, especially related to inotifywait. Please help.

In first loop, I am trying to monitor the /uploads folder, the moment it finds the .csv file, it checks if the filename has space. If yes, it wants to change the space to underscore in the filename. I have been trying to find a way to find "space, () or ," in the filename but only could do the 'space' part change. This is giving me an error that file cannot be moved, no such file or directory.

Second loop works separately but not when incorporated with first loop as there are errors which I have not been able to debug. If I run second loop separately, it is working correctly. But if there is a way to optimize the code better in one loop, I would be happy to know. Thanks!

Example: folder name: /../../upload

filenames: abc_123.csv (code should not make any change) , pqr(12 Apr).csv (code should change it to pqr_12_Apr.csv), May 12.csv (code should change it to May_12.csv) etc. Once these 3 files have proper naming, it should be ready to be uploaded through sql loader and once files are processed, they get deleted.
My code is:

#!bin/bash
inotifywait -mqe create /../../upload | while read file; do
    if [[ $file = '* *'.csv]]; then
        mv "$file" ${file// /_}
    fi
done

for file in /../..upload/*.csv
do
       sqlcommand="sqlldr user/pwd control="/../xxx.ctl" data=$file silent=feedback, header"
       $sqlcommand
       rm $file
done

Thank you!


Solution

  • I have modified your script to this,

    #!/usr/bin/env bash
    
    while IFS= read -r file; do
      filename=${file#* CREATE }
      pathname=${file%/*}
      if [[ $pathname/$filename = *\ *.csv ]]; then
        echo mv -v "$pathname/$filename" "$pathname/${filename// /_}"
      fi
    done < <(inotifywait -mqe create /../../upload)
    
    • Remove the echo if you think the output is correct.
    • I just don't know how you can integrate the other parts of your script with that, probably create a separate script or remove the -m (which you don't want to do most probably). Well you could use a named pipe if mkfifo is available.

    EDIT: as per OP's message add another parameter expansion for another string removal.

    Add the code below the if [[ ... ]]; then

    newfilename=${filename//\(\)}
    

    Then change "${filename// /_}" to "${newfilename// /_}"