I'm not a BASH programmer and whenever I have to create scripts it's a lottery for me, so apologies if my script looks too redudant or written by a newbie.

As a foreword I have many screen snapshots taken on a Windows machine where the two display are captured. I organized them in subfolders and I want to take a general approach to crop images in them. As an aside, since I don't like filename as Windows generates them, i.e. with spaces and parenthesys, I want to remove such characters.

All above is just one of many cases where I may have to apply actions to files residing in subfolders. I organized the script by actions to be taken on files.

Now to the point: in wring the script I wanted it to be general purpose and hene I tried to have functions behaving like other scripting languages trying not to use global variables if not stricly necessary.

Now the point: since I have to assign strings to variables eventually I was forced to use "echo -n" in a subshell I read opposite comments on usign echo in a subshell to assign a string made of spaces or other special characters to a variable.

I tested one by one and on their own the three functions here below and they worked. That means that when required I forced values in the function itself.

As soon as I nested them in the third one the only thing I know is that if I didn't use this tecnique of echoing the variable in a subshell and capturing the output it would never have worked: except for a variable, explained at the bottom.

trim_weird_char () {
#  set +x
  local _bn="$(basename "$1")"
#  echo "[twc bn] $_bn"
  local _dn="$(dirname "$1")"
#  echo "[twc dn] $_dn"
  local _fn="$(echo -n $_bn | tr -d ' ' | tr -d '(' | tr -d ') ')"
#  echo "[twc fn] $_fn"
  local _ifn="$(echo -n "${_dn}"/"${_bn}")"
  local _dfn="$(echo -n "${_dn}"/"${_fn}")"
  mv "$_ifn" "$_dfn"
  echo "$_dfn"
#  set -x

crop_img() {
# set +x
  #$1 = image
  #$2 = resize
  #$3 = string to add in the output filename before the extension
  local _img="$(echo -n "$1")"; # we want the file name and hence we remove the extension by NOT being GREEDY with the removal
  local _fn="$(echo -n "${_img%.*}")"
  local _ext="$(echo -n "${_img##*.}")"; # we want the extension and hence we remove what comes before by being GREEDY with the removal
  local _dfn="$(echo -n "${_fn}${3}.${_ext}")"
  convert "$_img" -crop "$2" "$_dfn"
  echo "$(echo -n "$_dfn")"

crop_smartbe () {
# set -x
# ls -la | awk '{print $5}'
  echo -n "Trimming name for $1..."
  local _img="$(trim_weird_char "$1")"
  echo "done: $_img"
  echo -n "Cropping $_img to... "
  local _s="$(ls -la "$_img" | awk '{print $5}')"
  local _dfn="$(echo -n $(crop_img "$_img" "1080x1920+0+0" "_cropped"))"
  local _s_img=$(ls -la "$_dfn" | awk '{print $5}')
  echo "$_dnf done: size from $_s to $_s_img"

A filename I tested my functions on is the following (I source'd the script above)

gadger@brunas:/brunas/expenses/2020/Demandes de reimbursement/Demandes$ crop_smartbe Full/1261597\ -\ Frais\ Internet\ -\ 1er\ sémestre/Screenshot\ \(142\).png
Trimming name for Full/1261597 - Frais Internet - 1er sémestre/Screenshot (142).png...done: Full/1261597 - Frais Internet - 1er sémestre/Screenshot142.png
Cropping Full/1261597 - Frais Internet - 1er sémestre/Screenshot142.png to...  done: size from 292631 to 100694

For this (in crop_smartbe)

local _dfn="$(echo -n $(crop_img "$_img" "1080x1920+0+0" "_cropped"))"
echo "$_dnf done: size from $_s to $_s_img"

still $_dnf is not assigned correctly even though I used the echo -n tecnique.

Taken for granted that removing the echo function breaks the script, shall I prefer printf instead? Or should I rewrite the script in a different manner that doesn't require the use of echo? In case how?

Thanks Alex

  • What do you actually want to achieve with all this? Dec 6, 2020 at 22:31
  • @roaima: eventually by using convert I want to rename and crop images that reside in subdirectories. I will do a find <dir> -iname "*" -exec crop_smartbe {} \;
    – Alex
    Dec 6, 2020 at 22:36
  • It you define your requirements along with your current code is far easier for people to understand why your code is written how it is, and therefore how to make suggestions. Telling you how to solve an issue that's the result of a fundamentally wrong approach to something benefits no-one. (I'm not necessarily saying your approach is wrong; it's more that it seems awfully complicated for what I would have thought was a simple task. But as I can't work out what you're trying to achieve I'm still not sure) Dec 6, 2020 at 22:40
  • @roaima: I rewrote it, I hope it's clearer now.
    – Alex
    Dec 6, 2020 at 22:51
  • 1
    In almost all of those assignments, the command substitution and echo are unnecessary, just assign local _img="$1" and local _fn="${_img%.*}" etc. Same here: echo "$(echo -n "$_dfn")", just do echo "$_dfn" instead. It doesn't matter if you use echo or echo -n in something that's used in a command substitution, the tailing newlines get removed anyway.
    – ilkkachu
    Dec 6, 2020 at 23:01


You must log in to answer this question.

Browse other questions tagged .