0

I'm looking to extract part of filename which I"m currently using position but it's not working as desired output.

Sample data:

ls -a *0728*dat | sort

amnbmnbm_jnjmnm_sd_07282019_14_13_17.dat
amnbmnb_kjhkj_07282019_11_23_22.dat
njnkjnjk_AbnBCBB_DE_07282019_07_09_04.dat

I'm looking to extract the file part from the filename everything leftside from the date on wards including underscore(_) and assign it to vairable

Desired output:

variable file is something it needs to hold the values, so that I can pass in for loop

file:

amnbmnbm_jnjmnm_sd_
amnbmnb_kjhkj_
njnkjnjk_AbnBCBB_DE_


for file_name in "${file[@]}"
do

echo " file_name=$file_name"

done

Desired output:

amnbmnbm_jnjmnm_sd_
amnbmnb_kjhkj_
njnkjnjk_AbnBCBB_DE_
Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
Kiran
  • 29

3 Answers3

1

Perhaps:

for file_name in *0728*dat
do
  printf '%s\n' "${file_name%[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]_[0-9][0-9]_[0-9][0-9]_[0-9][0-9].dat}"
done

This strips from the end of each filename the pattern of: 8 digits, underscore, 2 digits, underscore, 2 digits, underscore, 2 digits, then .dat.

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
0

using sed:

ls -a *0728*dat | sed 's/[0-9].*//'
amnbmnb_kjhkj_
amnbmnbm_jnjmnm_sd_
njnkjnjk_AbnBCBB_DE_

or

ls -a *0728*dat | sed "s/[0-9]\{8\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}\.dat$//"
Siva
  • 9,077
0

The following requires bash 4.4 or newer, GNU find and GNU sed (or, at least a find and a sed that support NUL as the output/input separator):

$ mapfile -d '' files < <(find . -maxdepth 1 -type f -iname '*0728*.dat' -print0 | 
    sed -z 's:^\./::; s/[0-9][0-9_]\+.dat//')

This populates a bash array (files) with the matching filenames in the current directory after they've had the leading ./ and the date & time & .dat extension stripped by sed. It uses NUL as the record (i.e. filename) separator to avoid any potential issues with spaces, line-feeds, shell meta-characters, etc in any of the filenames.

find is used because you should never use the output of ls as input to other programs or as arguments on another program's command-line - it is unsafe and unreliable. See Why not parse ls (and what to do instead)?

The find command can, of course, be modified to find files matching different patterns, or in sub-directories, etc.

Example:

$ touch amnbmnbm_jnjmnm_sd_07282019_14_13_17.dat amnbmnb_kjhkj_07282019_11_23_22.dat \
    njnkjnjk_AbnBCBB_DE_07282019_07_09_04.dat

$ mapfile -d '' files < <(find . -maxdepth 1 -type f -iname '*0728*.dat' -print0 | 
    sed -z 's:^\./::; s/[0-9][0-9_]\+.dat//')

$ typeset -p files
declare -a files=([0]="amnbmnbm_jnjmnm_sd_" [1]="amnbmnb_kjhkj_" [2]="njnkjnjk_AbnBCBB_DE_")

$ printf '%s\n' "${files[@]}"
amnbmnbm_jnjmnm_sd_
amnbmnb_kjhkj_
njnkjnjk_AbnBCBB_DE_
cas
  • 78,579