Search code examples
bashgrepfindxargs

How to move all files in a subfolder except certain files


I usually download with filezilla in the directory /Public/Downloads on my nas.

I made a script executed by filezilla when download queue is finished, so all my downloads are moved to /Public/Downloads/Completed. My directory /Public/Downloads contains also two files and three directories that must not be moved.

folder.jpg
log.txt
Temp
Cache
Completed

I tried this command:

find /Public/Downloads/* -maxdepth 1 | grep -v Completed | grep -v Cache | grep -v Temp | grep -v log.txt | grep -v folder.jpg | xargs -i mv {} /Public/Downloads/Completed

This works for downloaded files and folders named without special characters: they are moved to /Public/Downloads/Completed But when there is a <space> or an à or something else special, xarg is complaining unmatched single quote; by default quotes are special to xargs unless you use the -0 option

I've searched a solution by myself but haven't find something for my needs combining find, grep and xargs for files and directories.

How do I have to modify my command ?


Solution

  • This is just a suggestion for your change strategy and not about xargs. You only need the bash shell and mv for the external tool.

    #!/usr/bin/env bash
    
    shopt -s nullglob extglob
    
    array=( 
      folder.jpg
      log.txt
      Temp
      Cache 
      Completed
    )
    
    to_skip=$(IFS='|'; printf '%s' "*@(${array[*]})")
    
    for item in /Public/Downloads/*; do
      [[ $item == $to_skip ]] && continue
      echo mv -v "$item" /Public/Downloads/Completed/ || exit
    done
    
    • Remove the echo if you think that the output is correct.
    • Add the -x e.g. set -x (after the shebang) option to see which/what the code is doing or bash -x my_script, assuming my_script is the name of your script.