-1

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/Files/Apr1995/1995__.info,

Desktop/Files/Apr1995/1995__.dat,

Desktop/OtherFiles/1995/info,

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

or

 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

Will
  • 3
  • 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 08: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 08: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 08:41
  • @Kusalananda Ah yes, I didn't pick up on that. Cheers. – Sparhawk Mar 10 '18 at 09:03

2 Answers2

0

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: \*

Nasir Riley
  • 11,422
  • 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 09: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
0
for a in `find ~+ -type f -path '*199[0-9]*' -iname '199[0-9]*.*'`
{
 if [[ $a =~ \.(dat|info)$ ]]
 then
  n=${a##*/}
  n=${n%.*}; x=${a##*.}
  d=RootNewDir/$n/$x
  mkdir -p $d
  mv $a $d/${n}__$x
 fi
}
  • 1
    Related: https://unix.stackexchange.com/questions/321697/why-is-looping-over-finds-output-bad-practice – Kusalananda Mar 10 '18 at 07:56
  • Also: https://unix.stackexchange.com/questions/131766/why-does-my-shell-script-choke-on-whitespace-or-other-special-characters and https://unix.stackexchange.com/questions/171346/security-implications-of-forgetting-to-quote-a-variable-in-bash-posix-shells – Kusalananda Mar 10 '18 at 07:58