0

I've exhausted every search I could.

I'm trying to read a filename/path from the CLI using read so I can link files for sorting in bulk. I've tried all sorts of things from quotation marks to none, trying to use eval to expand, and so many other things. None of them work.

Here's my script in it's current state:

#!/bin/bash
read -p "from? (explicit, folder/) " -e from
read -p "to? (explicit, folder/) " -e to
read -p "base filename before ep name? " -e formatOldStart
read -p "base filename after ep name? " -e formatOldEnd

...

  lnFrom=$from$formatOldStart$currentEpisodeNumber$formatOldEnd

  echo $lnFrom

  #ln "$lnFrom" "$lnTo"

Here's an example usage:

$ from? (explicit, folder/) $HOME/archive/_DATA_ARCHIVE/.data/Example\ Complete\ Series\ +\ Movies\ \[Dual\ Audio\]/Example\ \[Dual\ Audio\ DVD\ 480p\]/
$ to? (explicit, folder/) $HOME/archive/_DATA_ARCHIVE/_video_storage/Anime/Shows/Example/Season\ 1/
$ base filename before ep name? \(Hi10\)_Example_-_
$ base filename after ep name? _(DVD_480p)_(a-S)_(*).mkv

And then here's the output:

$HOME/archive/_DATA_ARCHIVE/.data/Example Complete Series + Movies [Dual Audio]/Example [Dual Audio DVD 480p]/(Hi10)_Example_-_015_(DVD_480p)_(a-S)_(*).mkv

Here's the expected output:

/home/user/archive/_DATA_ARCHIVE/.data/Example Complete Series + Movies [Dual Audio]/Example [Dual Audio DVD 480p]/(Hi10)_Example_-_015_(DVD_480p)_(a-S)_(6852D8ED).mkv

I was only able to get the expected output after manually inserting wildcards (not regex) and file names suggested from this post, but this obviously means that I have to edit this script manually every time I want to use it for a new folder without auto-complete. I have a LOT of stuff to categorize, so that is simply not possible.

  • Can you simplify this to the smallest possible bit of code that exhibits the problem you see ([mcve])? – Benjamin W. Apr 02 '20 at 16:05
  • @BenjaminW. Adjusted. Let me know if it's acceptable. – Dark Swordsman Apr 02 '20 at 16:23
  • The input line is just data, not code subject to shell expansion. `$HOME` is literal text that is never parsed as a shell variable. – chepner Apr 02 '20 at 16:45
  • 2
    I would recommend simply taking `from=$1; to=$2; ...` instead of prompting the user; the you can let the shell process `$HOME/archive/_DATA_ARCHIVE...` as desired before your script runs. – chepner Apr 02 '20 at 16:47
  • 1
    "this obviously means that I have to edit this script manually every time I want to use it for a new folder" What? Why? – that other guy Apr 02 '20 at 17:11
  • @chepner I just attempted that, but because some of the variables are only pieces of filenames, it can't glob it. The only way to get it to glob would be to use the full path and name, but then I'd just be specifying each file because I can't say "only episodes 028 to 054" on the command line. – Dark Swordsman Apr 02 '20 at 17:17
  • @thatotherguy Maybe I was unclear? The only way I got it to work previously was manually entering the file path into the script itself. This is not useful when I have tons of shows and prefer to use tab autocomplete. It would waste so much time. – Dark Swordsman Apr 02 '20 at 17:18
  • Ah. The example you pointed to used variables without hard coding paths. The reason why this is tricky is because you want different behavior for different parts of the expression: you want parameter expansion for `$HOME`, then you *don't* want pathname expansion for `[Dual Audio]`, then you *do* want pathname expansion for `(*).mkv`. Your current solution works because you've settled on a single standard for all of them: escaped shell words. That standard necessarily requires `eval`. I would probably have gone with a `find` or `rename.ul` style with literal from/to dir param plus a pattern – that other guy Apr 02 '20 at 17:36
  • @thatotherguy Thanks for the feedback. I'll heed your words for future reference. I updated my answer to also include a one liner that seems a lot easier and the only true auto-complete solution available. – Dark Swordsman Apr 02 '20 at 17:57

1 Answers1

0

Edit: After taking a different approach, I came up with a much easier one-liner that mostly works with tab complete (until the variables of course):

for index in {28..54}; do ln "/home/user/archive/_DATA_ARCHIVE/.data/Example Complete Series + Movies [Dual Audio]/Example [Dual Audio DVD 480p]/(Hi10)_Example_-_0${index}_(DVD_480p)_(a-S)_("*").mkv" "/home/user/archive/_DATA_ARCHIVE/_video_storage/Anime/Shows/Example/Season 2/Example S2E0${index}.mkv"; done

So I had someone help out and thankfully I was able to solve it.

First, we use -r in the read command to not parse the escape characters.

Then we assign the lnFrom and lnTo without quotes:

lnFrom=$from$formatOldStart$currentEpisodeNumber$formatOldEnd
lnTo=$to$formatNewStart$currentEpisodeNumber$formatNewEnd

Then we use eval on the ln command to parse the variables:

eval ln "$lnFrom" "$lnTo"

Now yes, I understand the issues with eval about it being a security issue, but this script is running on a closed network at my home, so I don't care.

If someone can provide a solution that works without eval, I'd be more than happy to accept that answer.

Sorry if this was obvious to a lot of you. I am familiar with JavaScript at work, but I am not super familiar with bash/unix besides basic commands to get around the OS.