4

I'm trying to write a shell script that moves all files except for the ones that end with .sh and .py. I also don't want to move directories.

This is what I've got so far:

cd FILES/user/folder
shopt -s extglob
mv !(*.sh|*.py) MoveFolder/ 2>/dev/null 
shopt -u extglob

This moves all files except the ones that contain .sh or .py, but all directories are moved into MoveFolder as well.

I guess I could rename the folders, but other scripts already have those folders assigned for their work, so renaming might give me more trouble. I also could add the folder names but whenever someone else creates a folder, I would have to add its name to the script or it will be moved as well.

How can I improve this script to skip all folders?

codeforester
  • 39,467
  • 16
  • 112
  • 140

2 Answers2

5

Use find for this:

find -maxdepth 1 \! -type d \! -name "*.py" \! -name "*.sh" -exec mv -t MoveFolder {} +

What it does:

  • find: find things...
  • -maxdepth 1: that are in the current directory...
  • \! -type d: and that are not a directory...
  • \! -name "*.py: and whose name does not end with .py...
  • \! -name "*.sh: and whose name does not end with .sh...
  • -exec mv -t MoveFolder {} +: and move them to directory MoveFolder

The -exec flag is special: contrary to the the prior flags which were conditions, this one is an action. For each match, the + that ends the following command directs find to aggregate the file name at the end of the command, at the place marked with {}. When all the files are found, find executes the resulting command (i.e. mv -t MoveFolder file1 file2 ... fileN).

xhienne
  • 5,738
  • 1
  • 15
  • 34
1

You'll have to check every element to see if it is a directory or not, as well as its extension:

for f in FILES/user/folder/*
do
   extension="${f##*.}"
   if [ ! -d "$f" ] && [[ ! "$extension" =~ ^(sh|py)$ ]]; then
       mv "$f" MoveFolder
   fi
done

Otherwise, you can also use find -type f and do some stuff with maxdepth and a regexp.

Regexp for the file name based on Check if a string matches a regex in Bash script, extension extracted through the solution to Extract filename and extension in Bash.

Community
  • 1
  • 1
fedorqui
  • 275,237
  • 103
  • 548
  • 598
  • I dont think this one worked. After i executed the script i got the following error: cannot move `/FILES/user/folder/' to a subdirectory of itself, `MoveFolder/folder' Than i added the 2>/dev/null part but now it doesn`t move anything. – Otorrinolaringologista -man Jan 07 '17 at 19:46
  • @Otorrinolaringologista-man I had incorrectly used `-e` to check if it was a file or a dir. Updated to check if it is not a directory. – fedorqui Jan 07 '17 at 19:50
  • It doesn`t show any errors but it also doesn`t move any file into MoveFolder – Otorrinolaringologista -man Jan 07 '17 at 19:55
  • @Otorrinolaringologista-man it is weird, it would need some debugging through `echo`s all around. Tested locally it works fine. – fedorqui Jan 07 '17 at 19:57
  • Well i just used echo to show $f and it just prints /FILES/user/folder once – Otorrinolaringologista -man Jan 07 '17 at 20:00
  • @Otorrinolaringologista-man I believe you did not add the `*` after `/FILES/user/folder` so that it expands to all the elements in the directory. That is, use `for f in FILES/user/folder/*`. – fedorqui Jan 07 '17 at 20:02
  • Now it reads all files in the directory but it also sends all files except directories, maybe there`s something else missing on the (sh|ph) part – Otorrinolaringologista -man Jan 07 '17 at 20:09
  • @Otorrinolaringologista-man ufff I am definitely grateful for your debugging, it wasn't my best fast approach. The error lies on checking the extension, where I was also checking for the dot. Updated. – fedorqui Jan 07 '17 at 20:11