0

Hello i am trying to move all files with .hi and .o extension from a target folder /src to another folder /Obj

So far i have tried:

    srcpath=$(pwd)"/src"

    ghc src/Main.hs > Logs/output.txt 2> Logs/Err.txt //this builds the project and generates the binaries and .hi files

    mv  *.hi *.o  $srcpath/src/ Obj/     //i want to move all these files to Obj/ folder but where do i place the extension arguments? 

How should the command be: mv extensions source dest ? or mv source dest extensions

I have tried:

srcpath=$(pwd)"/src"
objpath=$(pwd)"/Obj"

ghc src/Company.hs > Logs/output.txt 2> Logs/Err.txt

mv *.o *.hi  $srcpath  $objpath

And i get the following error:

    mv: cannot stat '*.o': No such file or directory
mv: cannot stat '*.hi': No such file or directory
mv: cannot move '/c/Users/[..]/src' to '/c/Users/[...]/Obj/src': Device or resource busy

2 Answers 2

2

With your command mv *.o *.hi $srcpath $objpath you are moving every file with *.o or *.hi plus the folder src from the current $(pwd) folder to Obj

If you want to move every *.o and *.hi which are located in the folder src, then you could use this:

#!/bin/bash
srcpath=$(pwd)"/src"
objpath=$(pwd)"/Obj"

mv $srcpath/*.o $srcpath/*.hi  $objpath

Make sure your bash script is running in the correct folder, so the $(pwd) command works properly.

Edit:

If you want to move a collection of files or files with a certain extension, you could change the script to look like that (thanks to https://stackoverflow.com/a/8880633/7311363):

#!/bin/bash

srcpath=$(pwd)"/src"
objpath=$(pwd)"/Obj"

##declare an array variable
declare -a arr=("*.o" "*.hi")

##loop trough the array to move
for i in "${arr[@]}"
do
    mv $srcpath/$i $objpath
done
4
  • So there is no way to issue a collection of extensions for a given source folder?You must add them manually? extension0 $srcpath.....extensionN $srcpath ?Is there no way to do [extension0...extensionN] $srcpath Commented Jul 12, 2018 at 9:55
  • 1
    I edited my answer, so you could move a collection of file names
    – chloesoe
    Commented Jul 12, 2018 at 10:47
  • Thank you very much but could you please explain 1. the @ stands for the index ? 2. when you write $srcpath/$i and i is 1 for example ,it selects all the files with the *.hi extension? Commented Jul 12, 2018 at 11:54
  • 1. yes, @ is the index. 2. yes, you could change the script to test and run mv $srcpath/${arr[1]} $objpath and then only the *.hi files would moved
    – chloesoe
    Commented Jul 12, 2018 at 14:29
2

You seem to treat *.o and *.hi as some kind of filters used by mv. This is not how it works. The tool expects paths. Your shell can expand *.o and *.hi to all suitable local paths from the current directory; if it worked, mv would see paths, not patterns. Apparently you have no matching files so these patterns are not expanded and get to mv as they are, hence

mv: cannot stat '*.o': No such file or directory

etc.

These syntax may work:

mv ./src/*.o ./src/*.hi ./obj/

Still it will (somewhat) fail if there are no matching files in ./src. You can introduce variables as you did, but

  • you probably don't need $(pwd), srcpath="./src" should be enough;
  • in general you should quote your variables (but not patterns), e.g.:

    mv "$srcpath"/*.o "$srcpath"/*.hi "$objpath"
    

If there are too many files, you will hit argument list too long.


This alternative solution using find should work with high number of files or no files at all:

find "$srcpath" -name "*.o" -o -name "*.hi" -exec mv {} "$objpath" \;

See man 1 find to learn how -exec works. Also note that thanks to the quotes, strings like "*.o" are not expanded by the shell here; find gets them literally and uses its intrinsic pattern matching procedure.

The solution will run a separate mv for every file. We can pass many arguments to mv thanks to find … -exec … {} + syntax, but since the syntax requires these arguments to be at the very end, we need mv to support -t (it's not required by POSIX, so your mv may or may not support it):

find "$srcpath" -name "*.o" -o -name "*.hi" -exec mv -t "$objpath" {} +

You must log in to answer this question.

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