Wednesday, May 8, 2024
 Popular · Latest · Hot · Upcoming
64
rated 0 times [  64] [ 0]  / answers: 1 / hits: 122171  / 2 Years ago, sun, march 6, 2022, 1:54:43

I have a script which searches all files in multiple subfolders and archives to tar. My script is



for FILE in `find . -type f  -name '*.*'`
do
if [[ ! -f archive.tar ]]; then

tar -cpf archive.tar $FILE
else
tar -upf archive.tar $FILE
fi
done


The find command gives me the following output



find . -type f  -iname '*.*'
./F1/F1-2013-03-19 160413.csv
./F1/F1-2013-03-19 164411.csv
./F1-FAILED/F2/F1-2013-03-19 154412.csv
./F1-FAILED/F3/F1-2011-10-02 212910.csv
./F1-ARCHIVE/F1-2012-06-30 004408.csv
./F1-ARCHIVE/F1-2012-05-08 190408.csv


But the FILE variable only stores first part of the path ./F1/F1-2013-03-19 and then the next part 160413.csv.



I tried using read with a while loop,



while read `find . -type f  -iname '*.*'`;   do ls $REPLY; done


but I get the following error



bash: read: `./F1/F1-2013-03-19': not a valid identifier


Can anyone suggest an alternative way?



Update



As suggested in the answers below I updated the scripts



#!/bin/bash

INPUT_DIR=/usr/local/F1
cd $INPUT_DIR
for FILE in "$(find . -type f -iname '*.*')"
do
archive=archive.tar

if [ -f $archive ]; then
tar uvf $archive "$FILE"
else
tar -cvf $archive "$FILE"
fi
done


The output that i get is



./test.sh
tar: ./F1/F1-2013-03-19 160413.csv
./F1/F1-2013-03-19 164411.csv
./F1/F1-2013-03-19 153413.csv
./F1/F1-2013-03-19 154412.csv
./F1/F1-2012-09-10 113409.csv
./F1/F1-2013-03-19 152411.csv
./.tar
./F1-FAILED/F3/F1-2013-03-19 154412.csv
./F1-FAILED/F3/F1-2013-03-19 170411.csv
./F1-FAILED/F3/F1-2012-09-10 113409.csv
./F1-FAILED/F2/F1-2011-10-03 113911.csv
./F1-FAILED/F2/F1-2011-10-02 165908.csv
./F1-FAILED/F2/F1-2011-10-02 212910.csv
./F1-ARCHIVE/F1-2012-06-30 004408.csv
./F1-ARCHIVE/F1-2011-08-17 133905.csv
./F1-ARCHIVE/F1-2012-10-21 154410.csv
./F1-ARCHIVE/F1-2012-05-08 190408.csv: Cannot stat: No such file or directory
tar: Exiting with failure status due to previous errors

More From » bash

 Answers
2

Using for with find is the wrong approach here, see for example this writeup about the can of worms you are opening.



The recommended approach is to use find, while and read as described here. Below is an example that should work for you:



find . -type f -name '*.*' -print0 | 
while IFS= read -r -d '' file; do
printf '%s
' "$file"
done


This way you delimit the filenames with null (0) characters, this means that variation in space and other special characters will not cause problems.



In order to update an archive with the files that find locates, you can pass its output directly to tar:



find . -type f -name '*.*' -printf '%p0' | 
tar --null -uf archive.tar -T -


Note that you do not have to differentiate between if the archive exists or not, tar will handle it sensibly. Also note the use of -printf here to avoid including the ./ bit in the archive.


[#29511] Sunday, March 6, 2022, 2 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
kilusy

Total Points: 171
Total Questions: 110
Total Answers: 128

Location: Cayman Islands
Member since Sat, Dec 5, 2020
3 Years ago
kilusy questions
;