1

As an example, I have a directory with multiple files in this general format:

dir1/identifier1_desiredName1.m
dir1/identifier1_desiredName2
dir1/identifier1_desiredName3.m
dir1/identifier2_desiredName1.m
dir1/identifier2_desiredName2.m
dir1/identifier3_desiredName1.m
dir1/identifier3_desiredName2.m
dir1/identifier3_desiredName3
dir1/identifier4_desiredName1.m
dir1/identifier4_desiredName2.m
dir1/jabberwocky-mimsy-borogoves
dir1/other--should-not-be-moved

I'm trying to come up with a script that separates the files by the identifier by making a directory using that identifier, and then move files with the same identifier into that directory.

By the end of the moving, I would like to have something like:

dir1/identifier1/desiredName1.m
dir1/identifier1/desiredName2
dir1/identifier1/desiredName3.m
dir1/identifier2/desiredName1.m
dir1/identifier2/desiredName2.m
dir1/identifier3/desiredName1.m
dir1/identifier3/desiredName2.m
dir1/identifier3/desiredName3
dir1/identifier4/desiredName1.m
dir1/identifier4/desiredName2.m
dir1/jabberwocky-mimsy-borogoves
dir1/other--should-not-be-moved

As of right now, I think that I'm on the right track for the directory making:

awk _ {print $1} | uniq | mkdir

Syntax probably isn't quite correct, but the general idea is to print out the first column, separated by _, omitting repeats, and then piping those names into mkdir. But then I'm at a loss for moving the files into the directories. I was thinking about using grep similarly (replacing mkdir above and then piping into mv), but I wasn't sure if it would work.

  • how about visualizing your issue? (for ex. `tree `) – RomanPerekhrest Feb 06 '18 at 18:52
  • 2
    As Roman says, please provide a short (i.e., no more than 17 lines) but illustrative example of what you have and what you want to do. *Do **not*** respond in comments; [edit] your question to make it clearer and more complete. Also, try to solve this yourself and tell us what you tried and what happened. – G-Man Says 'Reinstate Monica' Feb 06 '18 at 18:59
  • I took the liberty of expanding your example to match your description.  If my edit is wrong, fix it — but also fix or clarify your statements “I’ve got ***directories*** with multiple files” and “Each directory has about 3-5 files with the same identifier and about 150 files total” (now deleted).  But this raises the question: Do you want an `identifier1` directory at the top level, or do you want `dir1/identifier1` and `dir2/identifier1`? – G-Man Says 'Reinstate Monica' Feb 06 '18 at 20:16
  • And using a filename of `identifier_desiredName.m`  is not a very clear way of saying that you want `identifier_desiredName.m` to be *renamed* to `desiredName.m` in the `identifier` directory. – G-Man Says 'Reinstate Monica' Feb 06 '18 at 20:22
  • @G-Man Where does he ask for renaming the files? – Gerard H. Pille Feb 06 '18 at 20:25
  • 1
    Well, that’s kind-of my point.  By saying `identifier_desiredName.m` instead of `identifier_RestOfName.m`, they made [francois P](https://unix.stackexchange.com/q/422366/80216#422375) and me believe that they wanted the files renamed, and since they don’t show the result they want, they left it ambiguous. – G-Man Says 'Reinstate Monica' Feb 06 '18 at 20:36
  • @G-Man Got you. Let's see if we hear Trailing Penguin again. – Gerard H. Pille Feb 06 '18 at 20:39
  • Yeah, sorry that I'm not being very clear. This is my first post and I honestly wasn't sure how exactly what I wanted because I wasn't sure what I could expect. I actually DO want the files to be renamed, so I'll edit my post to reflect this and give a example of what I would want at as a final product. Thanks for bearing with me! – Trailing Penguin Feb 06 '18 at 21:13

2 Answers2

0

you can list your files in list from ls > list for example
then use a loop-read of it to build sub-folders & then move the files dispatching them in the good one from its name as a pattern filter.

here I made a test from empty files touch filename to demonstrate method

bash-4.4$ while read
> do
> if [ ! -d ${REPLY/_*/} ]; then
>    mkdir ${REPLY/_*/}
> fi
> done < list

bash-4.4$ #here directories are made then use similar method for moving files
bash-4.4$ while read; do  if [ -f $REPLY ] ; then mv $REPLY ${REPLY/_*/}/${REPLY/*_/} ; fi ;  done < list
bash-4.4$ tree
.
├── identifier
│   └── desiredName.m
├── identifier1
│   ├── desirename1.m
│   └── desirename.m
├── identifier2
│   └── desirename2.m
└── list

3 directories, 5 files
bash-4.4$ 5~

You can do direct use in shell or use similar syntax in a script of course.

francois P
  • 1,219
  • 11
  • 27
  • One is never too old to learn. Never seen the "${REPLY/_*/}" syntax before. – Gerard H. Pille Feb 06 '18 at 20:26
  • 2
    `for f in *` is generally ***much*** preferable to ``ls > list`` and ``read < list``. See [Why does my shell script choke on whitespace or other special characters?](https://unix.stackexchange.com/q/131766/80216) and also [Why is looping over find's output bad practice?](https://unix.stackexchange.com/q/321697/80216) – G-Man Says 'Reinstate Monica' Feb 06 '18 at 20:30
-1
find . -type f -name '*_*.m' | while read FP
do
  FN="${FP##*/}"
  DN="${FP%/*}"
  ID="${FN%_*}"
  echo $FP "=>" $DN "/" $ID "/" $FN
  mkdir "$DN/$ID" 2>/dev/null
  mv "$FP" "$DN/$ID"
done
Gerard H. Pille
  • 2,350
  • 9
  • 13
  • this keeps the full file name intead of desiredname.m :) no ? -- & test the directory is present is mush better than removing error messages by redirection to /dev/null :) – francois P Feb 06 '18 at 19:57
  • @francoisP I'm eagerly awaiting your solution. The OP did not request to alter the filenames. I hope the downvote had a valid excuse. – Gerard H. Pille Feb 06 '18 at 20:15
  • 1
    I didn’t vote, but see [Why is looping over find’s output bad practice?](https://unix.stackexchange.com/q/321697/80216) Also, we prefer answers with explanations. – G-Man Says 'Reinstate Monica' Feb 06 '18 at 21:04
  • Yeah, my bad for not being clear. Thanks anyway for the help! – Trailing Penguin Feb 06 '18 at 22:13
  • I down-voted because like G-Man said this is bad practice. Also you have not quoted some variables. – jesse_b Feb 06 '18 at 22:26
  • Well, thirty years on unix, and when I retire within 8 months, I won't have been a single day out of a job. All through bad practice. Life just isn't fair. – Gerard H. Pille Feb 07 '18 at 07:20