-3

I have a list of files like this

186866-Total-Respondents.csv
343764-Total-Respondents.csv
415612-Total-Respondents.csv
761967-Total-Respondents.csv

And I want to rename them by matching the first string of numbers above to the same string of numbers in a file called data.txt which is in the same directory.

The contents of data.txt is below

2018-09-Client-1-761967-Brand-1-Total-Respondents
2018-09-Client-1-415612-Brand-2-Two-Total-Respondents
2018-09-Client-1-186866-Brand-Three-Total-Respondents
2018-09-Client-2-343764-Brand1-Total-Respondents
2018-09-Client-3-347654-No-Name-Brand-Total-Respondents
2018-09-Client-3-109321-House-Brand-Total-Respondents

The end result is that the 4 matching files above will be renamed to

2018-09-Client-1-186866-Brand-Three-Total-Respondents.csv
2018-09-Client-2-343764-Brand1-Total-Respondents.csv
2018-09-Client-1-415612-Brand-2-Two-Total-Respondents.csv
2018-09-Client-1-761967-Brand-1-Total-Respondents.csv

I have found a similar question which uses sed and regex but I can't edit the regex to rename successfully.

I'm guessing that sed or awk would work well here?

Bruce
  • 29
  • 5
  • 1
    Welcome to SO. Stack Overflow is a question and answer site for professional and enthusiast programmers. The goal is that you add some code of your own to your question to show at least the research effort you made to solve this yourself. – Cyrus Sep 07 '18 at 07:06

2 Answers2

1
# you have list of files
touch 186866-Total-Respondents.csv 343764-Total-Respondents.csv  415612-Total-Respondents.csv 761967-Total-Respondents.csv

# and data.txt
cat >data.txt <<EOF
2018-09-Client-1-761967-Brand-1-Total-Respondents
2018-09-Client-1-415612-Brand-2-Two-Total-Respondents
2018-09-Client-1-186866-Brand-Three-Total-Respondents
2018-09-Client-2-343764-Brand1-Total-Respondents
2018-09-Client-3-347654-No-Name-Brand-Total-Respondents
2018-09-Client-3-109321-House-Brand-Total-Respondents
EOF

# and you need to join them on the first field from list and the 5th field from data
# got a little `while read` there, cause I got no good idea how to replace 4th occurence of char with a tab or space
# also I needed to add `.csv` suffix to the data.txt, but I could have just `sed 's/$/.csv/'
# xargs then eats every two arguments and runs mv
join -11 -25 -t- <(printf "%s\n" *.csv | sort) <(<data.txt sort -t- -k5) \
| while IFS=- read -r a b c r; do echo "$a-$b-$c" "$r".csv; done \
| xargs -n2 mv

The script will execute:

mv 186866-Total-Respondents.csv 2018-09-Client-1-Brand-Three-Total-Respondents.csv
mv 343764-Total-Respondents.csv 2018-09-Client-2-Brand1-Total-Respondents.csv
mv 415612-Total-Respondents.csv 2018-09-Client-1-Brand-2-Two-Total-Respondents.csv
mv 761967-Total-Respondents.csv 2018-09-Client-1-Brand-1-Total-Respondents.csv
KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • Thank you for your help... how does the `cat >list < – Bruce Sep 07 '18 at 07:32
  • You can for example use `printf "%s\n" *.csv ` or use `find . -type f -maxdepth 1 -name '*.csv' -printf '%P\n'`. Never use `ls` in script, it's for nice baeuty terminal printing, not for batch scripts. I edited the answer. – KamilCuk Sep 07 '18 at 07:41
  • Ok, this is definitely helping, thank you... I remoeed the `touch` line as the files are already in the directory, as is `data.txt` but the 3 lines starting with `join` look great... I just need to do some more testing... – Bruce Sep 07 '18 at 07:48
  • I can see you're sorting by column 5 in data.txt but how would it work if the ID was in column 4 or 5? Can that scenario be covered too? – Bruce Sep 07 '18 at 08:06
  • Isn't `sort -t- -k1` effectively the same as `sort`? – PesaThe Sep 07 '18 at 08:37
  • @bruce The `-k` option in sort chooses the column to sort by, and the `-1` and `-2` switches in join choose the column to join by with. I don't know what you mean by column 4 __or__ 5, then maybe like first extract the id to another/new column and then join. – KamilCuk Sep 07 '18 at 18:05
  • @PesaThe Yes, I think it is, couldn't find any cases why it wouldn't. So the first `sort -t- -k1` can be just shortened to just `sort`. – KamilCuk Sep 07 '18 at 18:08
1

If you have these two files, and you want to do it with awk, then this works:

awk -F "-" '(NR==FNR){a[$1]=$0;next}
            ($5 in a){system("mv "a[$5]" "$0".csv)}' file1 file2

with file1 the list of files and file2 the data file.

Another way would be if you just have the data file,

#!/usr/bin/env bash
while read -r line; do          # read a full line from data.txt
   IFS="-" read -r a a a a value a <<<"${line}"
   old="${value}-Total-Respondents.csv";  # build old name
   [[ -e "${old}" ]] && mv "${old}" "${line}.csv" # move if file exists
done < data.txt
kvantour
  • 25,269
  • 4
  • 47
  • 72
  • Heh, nice :) To continue the nitpicking though...I wouldn't really count on the fact that all files follow `value-Total-Respondents.csv`. I would probably use `f=("$value"-*.csv); ((${#f[@]}==1)) && mv "$f" ...` – PesaThe Sep 07 '18 at 13:18
  • @PesaThe Probably true, but this is not what the OP has in mind. Maybe he only wants to move `${value}-Total-Respondents.csv` but the same directory has `${value}-Partial-Respondents.csv`. This way the script would fail. – kvantour Sep 07 '18 at 13:21