-1

I don't know if this is possible using bash but it would be nice to be able to do this just using bash.

I receive bunch of files (regularly) with the following name pattern:

  • xxx___yyy___abc__def.pdf
  • xxxa___y_yy___fg-h___ijdfdak.pdf
  • xx___v-vv___a_fasl-bk___os___23l.pdf
  • etc.

And I need to rename and move them into directories:

  • ~/xxx/yyy/abc/def.pdf
  • ~/xxxa/y_yy/fg-h/ijdfdak.pdf
  • ~/xx/v-vv/a_fasl-bk/os/23l.pdf

Is it possible? Please help.

Pelangi
  • 401
  • 1
  • 4
  • 6
  • What effort did you make on your own? – Inian Apr 30 '20 at 06:44
  • Split your problem into smaller parts. First part: how to split a string by a delimiter? Google that and the first hit is: https://stackoverflow.com/questions/918886/how-do-i-split-a-string-on-a-delimiter-in-bash and this is already your solution. – fancyPants Apr 30 '20 at 06:45
  • I am looking into the answer to that post ... looking promising. Thanks for pointing. I will update this post once I got that working. – Pelangi Apr 30 '20 at 07:02
  • Can't get multi-characters separator work with `IFS`. – Pelangi Apr 30 '20 at 07:55
  • 2
    @Pelangi: Do not limit yourself only with the first (accepted) answer. Check other answers too. – Tsyvarev Apr 30 '20 at 08:25

2 Answers2

1

Make a folder based on two arguments like

mkdir -p ~/xxx/yyy/abc

move the file inside the folder

mv xxx___yyy___abc__def.pdf ~/xxx/yyy/abc/def.pdf

Or just make a script accept the file as argument

#!/bin/bash
FOLDER="$(echo $1 | tr -s '_' | cut -d "_" -f1)"
SUBFOLDER="$(echo $1 | tr -s '_' | cut -d "_" -f2)"
SUBSUBFOLDER="$(echo $1 | tr -s '_' | cut -d "_" -f3)"
FILE="$(echo $1 | tr -s '_' | cut -d "_" -f4)"
mkdir -p "~/${FOLDER}/${SUBFOLDER}/${SUBSUBFOLDER}"
mv "$1" "~/${FOLDER}/${SUBFOLDER}/${SUBSUBFOLDER}/${FILE}"

Usage: ./script.sh xxx___yyy___abc__def.pdf

Not fancy but it works.

ebvjr
  • 51
  • 4
0

Using parameter expansion.

#!/bin/sh

for f in *.pdf; do
  last=${f##*_} first=${f%%_*} 
  third=${f%$last*} third="${third%??*}"
  third=${third##*_} second=${f%$third*}
  second=${second%???*} second=${second##*_}
  echo mkdir -p ~/"$first/$second/$third" && \                                                                                                                                               
  echo mv -v "$f" ~/"$first/$second/$third/$last"
done

As per update of the OP's question. Should remove all underscores.

#!/bin/bash

for f in *.pdf; do
  new=$(awk -F'[_]+' -vOFS='/' '{$1=$1}1' <<< "$f")
  echo mkdir -p ~/"${new%/*}/" && \
  echo mv -v "$f"  ~/"$new"
done
  • Remove the echo to actually rename the files.

The actual out put without the echo

copied 'xx___v-vv___a_fasl-bk__os23l.pdf' -> '/home/Pelangi/xx/v-vv/a/fasl-bk/os23l.pdf'
removed 'xx___v-vv___a_fasl-bk__os23l.pdf'
copied 'xxxa___y_yy___fg-h__ijdfdak.pdf' -> '/home/Pelangi/xxxa/y/yy/fg-h/ijdfdak.pdf'
removed 'xxxa___y_yy___fg-h__ijdfdak.pdf'
copied 'xxx___vvv___abk__osl.pdf' -> '/home/Pelangi/xxx/vvv/abk/osl.pdf'
removed 'xxx___vvv___abk__osl.pdf'
copied 'xxx___yyy___abc__def.pdf' -> '/home/Pelangi/xxx/yyy/abc/def.pdf'
removed 'xxx___yyy___abc__def.pdf'
copied 'xxx___yyy___fgh__ijk.pdf' -> '/home/Pelangi/xxx/yyy/fgh/ijk.pdf'
removed 'xxx___yyy___fgh__ijk.pdf'
Jetchisel
  • 7,493
  • 2
  • 19
  • 18
  • Does it assume that number of characters per section is 3? If so, my example above is bad. I will updated my question. – Pelangi Apr 30 '20 at 07:51
  • Then post the exact/more example, I'm not assuming anything, I just parsed what was posted... – Jetchisel Apr 30 '20 at 07:55
  • I just updated my examples. Thanks. – Pelangi Apr 30 '20 at 07:56
  • @Pelangi so the new answer works for you? or not? – Jetchisel Apr 30 '20 at 08:49
  • thank you so much ... very close to exactly what I am after ... the only case that it doesn't is when I have a single underscore in the original file name, like the third case in my example. And that's what happened as well when I tried to use IFS as suggested in another post, it also process a single underscore. – Pelangi Apr 30 '20 at 09:44
  • I think I got it ... changing `new=$(awk -F'[_]+' -vOFS='/' '{$1=$1}1' <<< "$f")` to `new=$(awk -F'___' -vOFS='/' '{$1=$1}1' <<< "$f")` seems to have done it. – Pelangi Apr 30 '20 at 09:47
  • 1
    The `'[_]+'` is a regex that will match all `_` without hard coding how much underscores are there. – Jetchisel Apr 30 '20 at 09:49