Drumroll
Drumroll

Reputation: 61

Rename certain files recursively in a directory - Shell/Bash script

I've searched about everywhere, to come up with this script below. I can't figure out what the issue is here. I'm trying to loop through all the directories inside a directory called Extracted_Source to rename any files that is a CSV with an appended timestamp. Any help is appreciated.

I keep getting a

No such file or directory./Extracted_Source/*

Below is the source:

for files in ./Extracted_Source/*
do if ["$files" contains ".csv"]
then mv "$files" "${files%}_$(date "+%Y.%m.%d-%H.%M.%S").csv";
fi done; echo end

Upvotes: 0

Views: 515

Answers (2)

I0_ol
I0_ol

Reputation: 1109

I would use find

find ./Extracted_Source -type f -name "*.csv" | while -r read files; do mv "$files" "${files%.*}_$(date "+%Y.%m.%d-%H.%M.%S").csv"; done

This also has the added benefit of handling files containing spaces in the file name.

Here's the same thing in multi-line form:

find ./Extracted_Source -type f -name "*.csv" | \
while read -r files; do 
    mv "$files" "${files%.*}_$(date "+%Y.%m.%d-%H.%M.%S").csv"
done

You can also use process substitution to feed the while loop:

while read -r files; do 
    mv "$files" "${files%.*}_$(date "+%Y.%m.%d-%H.%M.%S").csv"
done < <(find ./Extracted_Source -type f -name "*.csv")

In your current script, ${files%} is not doing anything. The .csv part of the file is not being removed. The correct way is ${files%.*}.

Try this to see for yourself: for files in *; do echo "${files%.*}"; done

See the Bash Hackers Wiki for more info on this.

Upvotes: 1

Robert Seaman
Robert Seaman

Reputation: 2582

For a start, the error message means that you don't have any files or folders in ./Extracted_Source/. However, the following will work:

#!/bin/bash

for file in ./Extracted_Source/*/*.csv; do
    mv "$file" "${file/.csv}_$(date "+%Y.%m.%d-%H.%M.%S").csv";
done

echo end

This doesn't account for csv files which have already been moved.

Upvotes: 0

Related Questions