LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 11-15-2019, 08:55 PM   #1
bmxakias
Member
 
Registered: Jan 2016
Posts: 254

Rep: Reputation: Disabled
Question List folder name and time in one line to create a variable in bash


Hello

I have this code:

Code:
Please select something to restore [1, 2, 3 e.t.c]:"
# get the folders count
count=$(ls -ltd $INCDIR/*/ | wc -l)

select incvalue in $(ls -ltd $INCDIR/*/ | awk -F/ '{print $(NF-1)}'); do
  # if input is a number and is less than or equal to count
  if (( $REPLY && $REPLY <= $count )) 2> /dev/null; then
    break
  else
    echo "Your input ${REPLY} is not available. Please select a number from the list:"
  fi
The result is:

Code:
1) inc12    3) inc10   5) inc8    7) inc6    9) inc4   11) inc2
2) inc11    4) inc9    6) inc7    8) inc5   10) inc3   12) inc1
That is fine as i am having the newest folder by time first but i can't add time on them like:

Code:
1) 14:45 inc12    3) 14:45 inc10   5) 14:45 inc8    7) 14:45 inc6    9) 14:45 inc4   11) inc2
2) 14:45 inc11    4) 14:45 inc9    6) 14:45 inc7    8) 14:45 inc5   10) 14:45 inc3   12) 14:45 inc1
I tried to use something like (notice that i remove the "d" from the parameters as it was the only way to get it work in ssh):

Code:
ls -lt path/to/folders/ | awk '{print $8, $9}'
and from ssh it works:

Code:
00:35 inc12
00:35 inc11
00:35 inc10
00:35 inc9
00:34 inc8
00:34 inc7
00:34 inc6
00:34 inc5
00:34 inc4
00:34 inc3
00:33 inc2
00:31 inc1
again the newest folder by time first but when i use it on script:

Code:
select incvalue in $(ls -ltd $INCDIR/*/ | awk '{print $8, $9}'); do
i am getting this:

Code:
 1) 00:35
 2) /backup/folder1/16-11-2019/folder2/inc/inc12/
 3) 00:35
 4) /backup/folder1/16-11-2019/folder2/inc/inc11/
 5) 00:35
 6) /backup/folder1/16-11-2019/folder2/inc/inc10/
 7) 00:35
 8) /backup/folder1/16-11-2019/folder2/inc/inc9/
 9) 00:34
10) /backup/folder1/16-11-2019/folder2/inc/inc8/
11) 00:34
12) /backup/folder1/16-11-2019/folder2/inc/inc7/
13) 00:34
14) /backup/folder1/16-11-2019/folder2/inc/inc6/
15) 00:34
16) /backup/folder1/16-11-2019/folder2/inc/inc5/
17) 00:34
18) /backup/folder1/16-11-2019/folder2/inc/inc4/
19) 00:34
20) /backup/folder1/16-11-2019/folder2/inc/inc3/
21) 00:33
22) /backup/folder1/16-11-2019/folder2/inc/inc2/
23) 00:31
24) /backup/folder1/16-11-2019/folder2/inc/inc1/
How should i adjust my code it to get it as:

Code:
1) 00:35 inc12
2) 00:35 inc11
3) 00:35 inc10
4) 00:35 inc9
5) 00:34 inc8
6) 00:34 inc7
7) 00:34 inc6
8) 00:34 inc5
9) 00:34 inc4
10) 00:34 inc3
11) 00:33 inc2
12) 00:31 inc1
and then be able to use $incvalue and get only the name like inc8 and not the date in the variable...

Thank you !

Last edited by bmxakias; 11-16-2019 at 12:01 AM.
 
Old 11-16-2019, 12:11 AM   #2
rigor
Member
 
Registered: Sep 2003
Location: 19th moon ................. ................Planet Covid ................Another Galaxy;............. ................Not Yours
Posts: 705

Rep: Reputation: Disabled
Hi bmxakias!

I'm not entirely clear of what the scope is of what you're doing, or whether or not you wish to display the time, etc., in the selection list display. I can see that, in your example at least, the date is part of the path to the file; so I realize that you might obtain the date on which someone wishes to focus, outside the scope of the example you've showed us. One way or another, I get the impression that the problem you're having relates to the way select parses things.

I'm particularly confused because this is a "Non-*NIX Forum" and yet you seem to be using things that are *NIX related; even if you're using Cygwin, I would tend to think of it as in some way Unix/Linux related.

I'll show you what I'd think of as a full blown example, and you can always cut it down to focus just on the elements you wish.

sel_restore.bash:

Code:
#!/bin/bash

echo "Please select something to restore [1, 2, 3 e.t.c]:"
# get the folders count
count=$(ls -ltd $INCDIR/* | wc -l)

select incvalue in $(ls -ldt --time-style=+%s  $INCDIR/* | gawk -e '{ print strftime( "%a_%b_%e_%H:%M:%S_%Z_%Y" , $6) ":_" $7;}')
    do
        # if input is a number and is less than or equal to count
        if (( $REPLY && $REPLY <= $count )) 2> /dev/null
            then
                break
            else
                echo "Your input ${REPLY} is not available. Please select a number from the list:"
        fi
    done
When I run that script with INCDIR having the value 'a_dir' and "inc" files 1 through 12, I get this:
Code:
./sel_restore.bash
Please select something to restore [1, 2, 3 e.t.c]:
 1) Fri_Nov_15_23:28:03_CST_2019:_a_dir/inc_12
 2) Fri_Nov_15_23:28:01_CST_2019:_a_dir/inc_11
 3) Fri_Nov_15_23:27:59_CST_2019:_a_dir/inc_10
 4) Fri_Nov_15_23:27:57_CST_2019:_a_dir/inc_9
 5) Fri_Nov_15_23:27:55_CST_2019:_a_dir/inc_8
 6) Fri_Nov_15_23:27:53_CST_2019:_a_dir/inc_7
 7) Fri_Nov_15_23:27:51_CST_2019:_a_dir/inc_6
 8) Fri_Nov_15_23:27:49_CST_2019:_a_dir/inc_5
 9) Fri_Nov_15_23:27:47_CST_2019:_a_dir/inc_4
10) Fri_Nov_15_23:27:45_CST_2019:_a_dir/inc_3
11) Fri_Nov_15_23:27:43_CST_2019:_a_dir/inc_2
12) Fri_Nov_15_23:27:41_CST_2019:_a_dir/inc_1
#? 99
Your input 99 is not available. Please select a number from the list:
#? 
 1) Fri_Nov_15_23:28:03_CST_2019:_a_dir/inc_12
 2) Fri_Nov_15_23:28:01_CST_2019:_a_dir/inc_11
 3) Fri_Nov_15_23:27:59_CST_2019:_a_dir/inc_10
 4) Fri_Nov_15_23:27:57_CST_2019:_a_dir/inc_9
 5) Fri_Nov_15_23:27:55_CST_2019:_a_dir/inc_8
 6) Fri_Nov_15_23:27:53_CST_2019:_a_dir/inc_7
 7) Fri_Nov_15_23:27:51_CST_2019:_a_dir/inc_6
 8) Fri_Nov_15_23:27:49_CST_2019:_a_dir/inc_5
 9) Fri_Nov_15_23:27:47_CST_2019:_a_dir/inc_4
10) Fri_Nov_15_23:27:45_CST_2019:_a_dir/inc_3
11) Fri_Nov_15_23:27:43_CST_2019:_a_dir/inc_2
12) Fri_Nov_15_23:27:41_CST_2019:_a_dir/inc_1
#? 12
I put underscores in the full blown date and time value to prevent "select" from parsing it into multiple values, as well after the colon between the date time and the filename.

Hopefully you can adjust this to suit your needs.

Last edited by rigor; 11-17-2019 at 01:58 AM.
 
Old 11-16-2019, 12:30 AM   #3
bmxakias
Member
 
Registered: Jan 2016
Posts: 254

Original Poster
Rep: Reputation: Disabled
It is close to what i would like to do but as a variable if i select for example 5 i am getting:

Quote:
Fri_Nov_15_23:27:49_CST_2019:_a_dir/inc_5
but i like to get only the:

Quote:
inc5
 
Old 11-16-2019, 12:57 AM   #4
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,011

Rep: Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194Reputation: 3194
You can use parameter substitution to get the desired information.

Code:
incvalue='Fri_Nov_15_23:27:49_CST_2019:_a_dir/inc_5'

echo "${incvalue#*/}"
 
Old 11-16-2019, 02:53 AM   #5
Firerat
Senior Member
 
Registered: Oct 2008
Distribution: Debian sid
Posts: 2,683

Rep: Reputation: 783Reputation: 783Reputation: 783Reputation: 783Reputation: 783Reputation: 783Reputation: 783
I have already covered this in your another thread

Code:
# get the folders count
count=$(ls -ltd $INCDIR/*/ | wc -l)
Code:
Dirs=($INCDIR/*/)
count=${#Dirs[@]}
but you don't need count, you are simply using that to check $REPLY is valid
but here's the thing, $incvalue will be empty if $REPLY is invalid

http://tldp.org/LDP/Bash-Beginners-G...ect_09_06.html


how much control do you have over the naming of the directories ?
if you name them
Code:
mkdir "$( date +%F-%H:%M )_inc_${number}"
the the Dirs will be "globbed" in order

your code can be shrunk to
Code:
PS3="Please select a number from the list:"
select incvalue in $INCDIR/*/
do
    if [[ -z $incvalue ]]
    then
      echo Your input ${REPLY} is not available.
    else
      [[ $incvalue == quit ]] && exit
      echo $incvalue your commands here but not as echo
      break
    fi
done
now, if you want to complicate things and not name your dirs ( or if you can't )

Code:
#!/bin/bash
INCDIR=/path/to/dirs 
GetDirs () {
for i in ${INCDIR}/*/
do
  printf "%(%F-%H:%M)T %s\n" \
    "$( stat -c %Y "$i" )" \
    "$i"
done | sort -r
}

PlaceHolderName () {
local IFS="${IFS:(-1)}"
# I set IFS to be only newline

select incvalue in $( GetDirs ) 
do
  [[ $REPLY =~ ^[qQ]$ ]] && exit
  if [[ -z $incvalue ]]
  then
    echo Your input ${REPLY} is not available.
  else
    echo $incvalue your commands here but not as echo
    echo the Dir is ${incvalue#* }
    break
  fi
done
}

PlaceHolderName


#
see "man builtins" search for printf
see "man date" for %F-%H:%M explanation
see "man stat"


the trick with IFS would work with your code, if you feel you must do it that way


Edit:. this is just demo code, needs proper checks etc.

Last edited by Firerat; 11-16-2019 at 02:59 AM.
 
Old 11-16-2019, 03:40 AM   #6
Firerat
Senior Member
 
Registered: Oct 2008
Distribution: Debian sid
Posts: 2,683

Rep: Reputation: 783Reputation: 783Reputation: 783Reputation: 783Reputation: 783Reputation: 783Reputation: 783
more inline with your original code

my for loop, printf , stat , was overkill

the trick is IFS
Code:
oIFS=$IFS
IFS=${IFS:(-1)}
select incvalue in $( ls -ltd $INCDIR/*/ | cut -d\  -f 8- )
do    
  [[ $REPLY =~ ^[qQ]$ ]] && exit
  if [[ -z $incvalue ]]
  then
    echo Your input ${REPLY} is not available.
  else 
    echo $incvalue your commands here but not as echo
    echo the Dir is ${incvalue#* }
    break
  fi
done
IFS=$oIFS


#
 
Old 11-16-2019, 10:34 AM   #7
bmxakias
Member
 
Registered: Jan 2016
Posts: 254

Original Poster
Rep: Reputation: Disabled
Quote:
incvalue='Fri_Nov_15_23:27:49_CST_2019:_a_dir/inc_5'

echo "${incvalue#*/}"
using that code i do not get as output the inc5 and i am getting instead the full path....

Quote:
/backup/folder1/16-11-2019/folder2/inc/inc5/
Quote:
oIFS=$IFS
IFS=${IFS-1)}
select incvalue in $( ls -ltd $INCDIR/*/ | cut -d\ -f 8- )
do
[[ $REPLY =~ ^[qQ]$ ]] && exit
if [[ -z $incvalue ]]
then
echo Your input ${REPLY} is not available.
else
echo $incvalue your commands here but not as echo
echo the Dir is ${incvalue#* }
break
fi
done
IFS=$oIFS
At the end the ${incvalue#* } is not inc5 .... instead i am getting the full path:

Quote:
/backup/folder1/16-11-2019/folder2/inc/inc5/
Thank you
 
Old 11-16-2019, 12:04 PM   #8
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 22,041

Rep: Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348Reputation: 7348
please use code tags instead of quote tags.
need to know if there was a slash (/) at the end of that incvalue and also something wrong here:
Code:
echo the Dir is ${incvalue#* }
# or
echo the Dir is ${incvalue#*/}
# or probably something else?
But I do not really understand what is the expected behavior
 
Old 11-16-2019, 12:15 PM   #9
michaelk
Moderator
 
Registered: Aug 2002
Posts: 25,784

Rep: Reputation: 5937Reputation: 5937Reputation: 5937Reputation: 5937Reputation: 5937Reputation: 5937Reputation: 5937Reputation: 5937Reputation: 5937Reputation: 5937Reputation: 5937
I think

echo "${incvalue#*/}"

should be

echo "${incvalue##*/}"
 
Old 11-16-2019, 12:28 PM   #10
Firerat
Senior Member
 
Registered: Oct 2008
Distribution: Debian sid
Posts: 2,683

Rep: Reputation: 783Reputation: 783Reputation: 783Reputation: 783Reputation: 783Reputation: 783Reputation: 783
use
[code]
your code here
[/code]
instead of [quote][/quote]



Edit: I had the INCDIR hardcoded
reposting
Code:
INCDIR=${1:-.}
oIFS=$IFS
IFS=${IFS:(-1)}
select incvalue in $(ls -ltd ${INCDIR%/}/*/ | cut -d\  -f 8- )
do
  [[ $REPLY =~ ^[qQ]$ ]] && exit
  if [[ -z $incvalue ]]
  then
    echo Your input ${REPLY} is not available.
  else
    echo $incvalue your commands here but not as echo

    echo the Dir is ${incvalue#* ${INCDIR%/}/}
    # or
    incvalue=${incvalue%/}
    echo the Dir is ${incvalue##*/}

    break
  fi
done
IFS=$oIFS


#
but it is rather clumsy

no doubt you will want to work with the selected dir at some point

so the full path would be ${incvalue#* }

the "#* " removes everything up to and including the first space


read https://mywiki.wooledge.org/BashGuide
the whole of it!
before you continue with your scripting

it will help get rid of the bad habits you have picked up from other scripts

Last edited by Firerat; 11-16-2019 at 01:24 PM.
 
1 members found this post helpful.
Old 11-16-2019, 01:50 PM   #11
bmxakias
Member
 
Registered: Jan 2016
Posts: 254

Original Poster
Rep: Reputation: Disabled
Code:
oIFS=$IFS
IFS=${IFS:(-1)}
select incvalue in $(ls -ltd ${INCDIR%/}/*/ | cut -d\  -f 8- )
do
  [[ $REPLY =~ ^[qQ]$ ]] && exit
  if [[ -z $incvalue ]]
  then
    echo Your input ${REPLY} is not available.
  else
    incvalue=${incvalue%/}
    echo the Dir is ${incvalue##*/}

    break
  fi
done
IFS=$oIFS
The above code works great !!!!

One last:

The output of listing is like this:

Code:
21) 05:33 /backup/folder1/16-11-2019/folder2/inc/inc5/
can we adjust the code and do it as:

Code:
21) 05:33 inc5
?

Thank you
 
Old 11-16-2019, 03:06 PM   #12
michaelk
Moderator
 
Registered: Aug 2002
Posts: 25,784

Rep: Reputation: 5937Reputation: 5937Reputation: 5937Reputation: 5937Reputation: 5937Reputation: 5937Reputation: 5937Reputation: 5937Reputation: 5937Reputation: 5937Reputation: 5937
Select creates the menu based on the contents of your list. You need to change $INCDIR to just look in the last directory. Something like

$(ls -ltd /backup/folder1/16-11-2019/folder2/inc/ | cut -d\ -f 8- )

Somewhat more involved but you can create an array to look at the desired directories and change it based on what you want to display.

Code:
inclist=(  $(ls -ltd ${INCDIR%/}/*/ | cut -d\  -f 8- ) )

for i in "${!inclist[@]}"; do 
  echo "inclist: $i, value: ${inclist[$i]}"
 do some string manipulation here to remove path
 inclist[$i]=$new_value
done

select incvalue in "${inclist[@]}"
do
   
done

Last edited by michaelk; 11-16-2019 at 03:13 PM.
 
1 members found this post helpful.
Old 11-16-2019, 04:02 PM   #13
bmxakias
Member
 
Registered: Jan 2016
Posts: 254

Original Poster
Rep: Reputation: Disabled
Code:
$(ls -ltd /backup/folder1/16-11-2019/folder2/inc/ | cut -d\ -f 8- )
I am getting again the full path

This command does what i like to have as an output (except the numbers in front):

Code:
ls -lt /backup/mariadbfull/16-11-2019/databases/inc/ | grep "^d" | awk -F" " '{print $8,$9}'
result:

Code:
05:33 inc5
what i like is:

Code:
5) 05:33 inc5
and when a user select 5 to get as variable this: inc5

if that helps....


I can trick that and having the listing that i like and prompt the user to type the inc5 and get the variable as i link just inc5 using:

Code:
ls -ltr $INCDIR | egrep '^d' | awk '{print $8,$9}'

     echo ""
     echo ""
echo -e "Please select the inc [inc1, inc2, inc3 e.t.c]: \c"
read incvalue
But i prefer to be able the user to select by the numbers in front as the above doesn't have also any check about the user input...

If there is a typo it will not work....

Thank you

Last edited by bmxakias; 11-16-2019 at 04:27 PM.
 
Old 11-16-2019, 04:33 PM   #14
michaelk
Moderator
 
Registered: Aug 2002
Posts: 25,784

Rep: Reputation: 5937Reputation: 5937Reputation: 5937Reputation: 5937Reputation: 5937Reputation: 5937Reputation: 5937Reputation: 5937Reputation: 5937Reputation: 5937Reputation: 5937
So why can't you substitute the command using awk in place of your existing pne?
 
1 members found this post helpful.
Old 11-16-2019, 04:34 PM   #15
Firerat
Senior Member
 
Registered: Oct 2008
Distribution: Debian sid
Posts: 2,683

Rep: Reputation: 783Reputation: 783Reputation: 783Reputation: 783Reputation: 783Reputation: 783Reputation: 783
in all honesty things are starting to get messy

Code:
INCDIR=${1:-.}
oIFS=$IFS
IFS=${IFS:(-1)}
Dirs=( "$( ls -ltd ${INCDIR%/}/*/ | cut -d\  -f 8- )" )
select incvalue in ${Dirs[@]//${INCDIR%/}\/}
do
  [[ $REPLY =~ ^[qQ]$ ]] && exit
  if [[ -z $incvalue ]]
  then
    echo Your input ${REPLY} is not available.
  else
    echo $incvalue your commands here but not as echo
#   echo the Dir is ${incvalue#* ${INCDIR%/}/}
    incvalue=${incvalue%/}
    echo the Dir is ${incvalue#* }
    break
  fi
done
IFS=$oIFS


#
there are many ways to do what you ask

it really depends an what is going on with the rest of the script

and is just having the "time" useful? shouldn't you also have the date?
HH:MM isn't much use on its own
 
1 members found this post helpful.
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
bash: variable is a filename not a list ezekieldas Programming 4 02-15-2014 01:07 PM
[SOLVED] Please help script loop into the /tmp/filename.txt out put with filename and wc. dotran Linux - Newbie 10 06-08-2012 05:02 PM
grep query to list 1 line [which is fixed] and the next line after it [variable text] Glenn D. Linux - Software 3 01-20-2011 06:21 AM
AWK a variable Ouptut to a new variable and using the new variable with the old one alertroshannow Linux - Newbie 4 02-16-2009 12:08 AM
filename- and filename~ files? slinky2004 Linux - Newbie 5 10-17-2004 10:32 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 03:23 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration