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 <your dir>) – RomanPerekhrest Feb 6 '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 Feb 6 '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 Feb 6 '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 Feb 6 '18 at 20:22
  • 1
    Well, that’s kind-of my point.  By saying identifier_desiredName.m instead of identifier_RestOfName.m, they made francois P 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 Feb 6 '18 at 20:36
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.

-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
  • 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 6 '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 6 '18 at 20:15
  • 1
    I didn’t vote, but see Why is looping over find’s output bad practice? Also, we prefer answers with explanations. – G-Man Feb 6 '18 at 21:04
  • Yeah, my bad for not being clear. Thanks anyway for the help! – Trailing Penguin Feb 6 '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 6 '18 at 22:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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