Home > Back-end >  Execute rm with string on file and delete line
Execute rm with string on file and delete line

Time:09-02

I have a file (log.txt) with multiples lines.

Uploaded 1Y3JxCDpjsId_f8C7YAGAjvHHk-y-QVQM at 1.9 MB/s, total 3.9 MB
Uploaded 14v58hwKP457ZF32rwIaUFH216yrp9fAB at 317.3 KB/s, total 2.1 MB

Each line in log.txt represents a file that needs to be deleted. I want to delete the file and then delete the respective line.

Example:

rm 1Y3JxCDpjsId_f8C7YAGAjvHHk-y-QVQM

and after deleting the file that the log.txt contains, delete the line, leaving only the others.

Uploaded 14v58hwKP457ZF32rwIaUFH216yrp9fAB at 317.3 KB/s, total 2.1 MB

CodePudding user response:

Try this:

#!/bin/bash

logfile="logfile.txt"
logfilecopy=$( mktemp )
cp "$logfile" "$logfilecopy"

while IFS= read -r line
do
    filename=$( echo "$line" | sed 's/Uploaded \(.*\) at .*/\1/' )
    if [[ -f "$filename" ]]
    then
        tempfile=$( mktemp )
        rm -f "$filename" && grep -v "$line" "$logfile" >"$tempfile" && mv "$tempfile" "$logfile"
    fi
done < "$logfilecopy"

# Cleanup
rm -f "$logfilecopy"

It does:

  • keep a copy of the original log file.
  • read each line of this copy using while and read.
  • for each line, extract the filename. Note, done with sed since a filename could contain spaces. Therefore cut would not work as required.
  • If the file exists, delete it, remove the line from the log file and store it in a temporary file, move the temporary file into the log file.
  • that last step is done with && between commands to ensure that the last command is done before continuing. If the rm fails, the log entry must not be deleted.
  • finally delete the original log file copy.
  • you can add echo statements and-or -x to $!/bin/bash to debug if required.

CodePudding user response:

The following code reads log.txt line by line, extracts the filename from each line and tries to delete the file. It'll output the original line when the deletion fails, so you can directly generate a new log file containing the entries that haven't been deleted successfully:

#!/bin/bash

while IFS='' read -r line
do
    [[ $line =~ ^Uploaded\ (.*)\ at ]] &&
    rm -- "${BASH_REMATCH[1]}" ||
    echo "$line"
done < log.txt > log.txt.new &&
mv log.txt.new log.txt

remark: the while loop result is always true unless log.txt cannot be read or log.txt.new cannot be generated, so chaining the mv after a && makes it robust

  • Related