1

I have files in folder. which look like

1232_2019_02_09_12_29_29.txt
1232_2019_02_09_12_29_55.txt

I want to extract 2019_02_09_12_29_29 & 2019_02_09_12_29_55 from file name and convert into 2019-02-09-122929 & 2019-02-09-122955.

#!/bin/sh

path=$1

if [[ -z $1 ]];then
        echo "USAGE:: Argument missing, supply full path to list all files"
        exit 1
fi

if [ -f $path/all_files.txt ] ; then
    rm -f $path/all_files.txt
fi

ls -l $path | grep -v "^d" | awk '{print $9}' > $path/all_files.txt

while read -r line
do
        line=${line##*/}
#       echo "${line%"/}"
        ex1=`awk -F'|' '{print substr($1,length($1)-22, 19)}'`
#       ex2=`awk -F'|' '{print substr($1,length($1)-19, 10)}'`
        echo $ex1
        ex2=$(echo $ex1 | cut -c 1-10)
        echo $ex2
        ex3=$(echo $ex1 | cut -c 12-20)
        echo $ex3
done <$path/all_files.txt

But this code is not giving me desired output.

2

You can replace entire while loop with this line:

awk -F'[._]' '{print $2"-"$3"-"$4"-"$5$6$7}' $path/all_files.txt

If you want to keep the extension of the files (.txt) you should use command like this:

awk -F_ '{print $2"-"$3"-"$4"-"$5$6$7}' $path/all_files.txt
0

I don't understand why you get downvote.
You are new contributor.
You give your research/effort.
So you are welcome and sorry for bad english.

First, you write #!/bin/sh and after you use if [[ -z $1 ]]
Not all sh shell handle [[ , so use if [ -z "$1" ]
Always quote your var like "$1"
Don't use ls in a script
You look for *.txt files so don't name your file all_files.txt, name it with .log
Don't use grep cut ... if you use awk or sed because awk and sed can handle that alone.
Don't read a file line by line when you use awk which can do that.

You can try this way :

#!/bin/sh

if [ -z $1 ];then
    echo "USAGE:: Argument missing, supply full path to list all files"
    exit 1
fi

log="$1/all_files.log"

if [ -f "$log" ] ; then
  rm -f "$log"
else
  echo "no file to rm"
fi

echo "with gnu sed"
find "$1" -maxdepth 1 -type f -name '*.txt' |
  sed 's/[^_]*_//;s/_//4g;s/_/-/g' # > "$log"

echo "with awk"
find "$1" -maxdepth 1 -type f -name '*.txt' |
  awk -F\_ '{for(i=2;i<5;i++)a=a$i"-";a=a$(i++)$(i++)$i;print a;a=""}' # > "$log"
0

I have used below method to achieve the same

awk -F "_" 'OFS="-"{$1="";print $0}' filename|sed "s/\..*//g"| sed 's/^-//g'| awk '{print substr($1,1,13)substr($1,15,2)substr($1,18)}'

output

2019-02-09-122929
2019-02-09-122955
0
#!/bin/sh

# Given arguments:
#    A single directory path to somewhere that has *.txt files.
# Assumption:
#    All *.txt files have filenames on the format XXXX_YYYY_MM_DD_hh_mm_ss.txt.
# Output:
#    The YYYY_MM_DD_hh_mm_ss part of each filename on the format YYYY-MM-DD-hhmmss.

# Set the positional parameters to the list of pathnames in the given directory.
set -- "$1"/*.txt

# Turn off filename globbing and set field splitting delimiter to an underscore.
set -f
IFS='_'

# Loop over the positional parameters generated above.
for pathname do
    # If this is not a regular file (or a symbolic link to one), skip.
    [ ! -f "$pathname" ] && continue

    # Get the filename portion of the pathname and delete the filename suffix.
    filename=$( basename "$pathname" .txt )

    # Delete the bit up to the first underscore in the remaining string.
    filename=${filename#*_}

    # Rely on the shell's word splitting to split the sting up into
    # separate words and then use printf to assemble the words inte the
    # format that we want.
    printf '%s-%s-%s-%s%s%s\n' $filename
done

Testing:

$ ls dir
1232_2019_02_09_12_29_29.txt  1232_2019_02_09_12_29_55.txt
$ sh script.sh dir
2019-02-09-122929
2019-02-09-122955

Related:

0

Using sed:

sed 's/^[^_]*_\(.*\)\..*$/\1/;y/_/-/;s/-\([^-]*\)-\([^-]*\)$/\1\2/' \
     $path/all_files.txt 

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.