I have a bunch of files in sub-directories that I want to move to a different directory.

The directories are organized in one parent directory like this: Apr1995 Apr1996 Aug1995 etc... (month then year)

so /Files/Apr1995 for example.

the files are formatted like this 1995___.info or 1995___.dat

I want to go into each sub directory and move files to a different directory where the sub directories are separated by year and then format. Something like this:

OtherFiles/1995/info, OtherFiles/1995/dat, OtherFiles/1996/info, etc.

The 1995 directory would have sub-directories named info and dat

In the end I want this organization for example:




Desktop/OtherFiles/1995/dat and so on

I've tried quite a few options like a couple of one liners:

 for d in ./*/ ; do (cd "$d" && mv 1995*.info /1995/info); done


 find ./ -type f -execdir mv 1995*.info /1995/info {} \;

I just get mv errors or it doesn't recognize that their are files like those.

A shell script could help too.

I'm kind of at a loss for something that seems relatively easy. Any help would be appreciated.

EDIT: hopefully the added info can help

closed as unclear what you're asking by G-Man, Sparhawk, DarkHeart, Jeff Schaller, Archemar Mar 11 '18 at 9:33

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • It is unclear where you would want to move the files and what your file hierarchy looks like both before and after the operation. Could you maybe add an example? – Kusalananda Mar 10 '18 at 8:02
  • 1
    I don't really understand the hierarchy either, but a few comments: you cd in the loop, but never cd back to the parent. Is /1995/info really the right path? – Sparhawk Mar 10 '18 at 8:37
  • @Sparhawk Well, the cd happens in a subshell, so that's ok, but it seems to me that files might get overwritten if the names of all files for a year are e.g. 1995___.info. – Kusalananda Mar 10 '18 at 8:41
  • @Kusalananda Ah yes, I didn't pick up on that. Cheers. – Sparhawk Mar 10 '18 at 9:03

Your second command will work but you didn't specify the file name. If you want to move all of the files matching the pattern of 1995_.info and/or 1995_.dat

find ./ -type f -name 1995*.info -exec mv {} /1995/info \;

find ./ -type f -name 1995*.dat -exec mv {} /1995/dat \;

If you want to do all years in one command:

for y in {1995..1999}; do $(find Years -type f -name $y*.info -exec mv {} '/'$y'/info' \;); done

for y in {1995..1999}; do $(find Years -type f -name $y*.dat -exec mv {} '/'$y'/dat' \;); done

That will loop through the directories with each year and find the filenames and move them to their yearly directories.

Sidenote: I tested and confirmed this in CentOS 7.4 but depending on the environment, you may need to escape the * so you can add a backslash in front of it: \*

  • Warning: If you have matching files in the current working directory, then the glob (*) will be expanded. Sidenote: when you don't have matching files, then it depends on shell settings, not distro (some distros may have different default settings). – ctrl-alt-delor Mar 10 '18 at 9:56
  • @cltr-alt-delor This is true. It does indeed depend on the environment. I've updated the answer to reflect this. – Nasir Riley Mar 10 '18 at 14:51
for a in `find ~+ -type f -path '*199[0-9]*' -iname '199[0-9]*.*'`
 if [[ $a =~ \.(dat|info)$ ]]
  n=${n%.*}; x=${a##*.}
  mkdir -p $d
  mv $a $d/${n}__$x

Not the answer you're looking for? Browse other questions tagged or ask your own question.