Find command to collect the file list having spaces
Linux - GeneralThis Linux forum is for general Linux questions and discussion.
If it is Linux Related and doesn't seem to fit in any other forum then this is the place.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
An alternative solution that does not use find, but rather a shell option and the stat command.
Code:
#!/bin/bash
days=1460
mypath="/Datafolder"
shopt -s globstar
secs=days*24*60*60
now=$(date +%s) # Time now in seconds since epoch
i=1
for f in $mypath/**/*; do
d=$(stat -c %Z "$f") # Time in seconds since epoch of last status change
if ((now - d > secs)); then
a[i]=$f
((i++))
fi
done
for ((i=1; i<=${#a[@]}; i++)); do
echo "${a[i]}"
done
#!/bin/bash
#declare array for later processing
fileArray=()
#split it to see it starting
echo "finding files..." | tee -a /tmp/MyList
while read f
do
#fill array
fileArray+=($f)
#want it in a file and output to screen too?
#echo "$f" | tee -a /tmp/MyList
#just put it in a file too?
#echo "$f" >> /tmp/MyList
done <<<$(find /Datafolder/ -type f -ctime +1460)
echo "here is the array filled"
echo "${fileArray[@]}"
echo "amount"
echo "${#fileArray[@]}"
if you got files with spaces within the file names you need to have double quotes around the string to separate the elements or keep them in order, how ever you look at it.
Code:
arrayWithSpaces=( "here is a space" "here is second space")
to get the elements and keep them in order when you access them.
Code:
fileArray+=('"'$f'"')
adds the double quotes to "file with spaces in it".
Actually adds quotes to everything. You might have to remove the quotes down the line to deal with it, which should not be a big deal.
I appreciate your efforts. Thank you. This is a nice trick you have written in that, it first collects the whole bunch of filenames in array named fileArray. And then in the end , you simple echo the contents of it all at once. My original script was also collecting the list and was able to print the whole contents of an Array. What I am seeking is , to be able to work on the individual contents of this array in a loop or so.
For example once the array has the list of older directories/files, I need to check this list , one by one, if the directories contain certain type of files. Or if the files pertaining to certain department.
For this to achieve basically I wish to create an Array and then iterate through the contents of this Array one by one using loop. Which is not working as the filenames contain multiple spaces.
array=()
while IFS= read -r -d $'\0'; do
array+=("$REPLY")
done < <(find /Datafolder/ -type f -ctime +1460 -print0)
REPLY is just the default variable for the read command.
From the find man pages.
Quote:
-print0
True; print the full file name on the standard output, followed by a null character (instead of the newline character that -print uses). This allows file names that contain newlines or other types of white space to be correctly interpreted by programs that process the find output.
I appreciate your efforts. Thank you. This is a nice trick you have written in that, it first collects the whole bunch of filenames in array named fileArray. And then in the end , you simple echo the contents of it all at once. My original script was also collecting the list and was able to print the whole contents of an Array. What I am seeking is , to be able to work on the individual contents of this array in a loop or so.
For example once the array has the list of older directories/files, I need to check this list , one by one, if the directories contain certain type of files. Or if the files pertaining to certain department.
For this to achieve basically I wish to create an Array and then iterate through the contents of this Array one by one using loop. Which is not working as the filenames contain multiple spaces.
also disregard the adding quotes to keep it in elements, I update that post, just reference it now as it is. that fixes the spaces in the file names issue. I was over thinking it, that is what was only needed.
Code:
array+=("$f")
keeps it in line.
and as with michaelk solution to adding to an array, to then check what you're looking for is, I assume you know what you're doing there, yes?
In addition, I do not know of a single line solution except for mapfile as posted which also why I have a loop. If you only need to iterate through the list once then an array isn't necessary.
Thanks Ondoho for this code. It works. But the Original script is much more complex and we need to collect the output of find in an array to be able to use it further down the script. So Array is important here.
you can add a counter to that loop and assign to an array:
Code:
#!/bin/bash
echo "Checking for older files now..." >>/tmp/list
array=()
count=0
find /Datafolder/ -type f -ctime +1460 | while read i
do
echo Files are "$i" >> /tmp/list
array[$((count++))]="$i"
done
(not tested. esp. not on bash 3.1)
I thought Turbocapitalist' solution was more elegant though.
I thought Turbocapitalist' solution was more elegant though.
Thanks but it's just a slight paraphrasing of grail's solution to a similar question I had the other week. I hadn't even seen mapfile before that. It's not in the POSIX shell that I normally script in.
# rpm -qa | grep bash
bash-3.1-24.26.20
# bash -version
GNU bash, version 3.1.17(1)-release (i586-suse-linux)
> mapfile
bash: mapfile: command not found
# which mapfile
which: no mapfile in (/sbin:/usr/sbin:/usr/local/sbin:/opt/gnome/sbin:/root/bin:/usr/local/bin:/usr/bin:/usr/X11R6/bin:/bin:/us
Thank you, that was exactly the information we needed to understand WHY it was not working for you.
The mapfile internal was added in version 4.x of bash. The "which" line would never find an internal bash command, because it does not exist out on the file system, it is withoin the bash executable in version 4 and up.
I have not used BASH 3 in a long time. I remember using some array based solutions, but not how I did it. If someone recalls the way, that may be faster than waiting for me to do the research.
OR, you could install a more modern BASH version if that is an option for you.
Could I ask why you are using 10 SP4? Both version 12 and version 15 use newer versions of BASH. Version 10 is almost ancient by current standards.
An array is important only if you want to treat certain elements in a special way.
The =( ) and the for loop's list split on IFS, while the latter has got the "${array[@]}" escape that you already applied in your post#1.
Code:
#!/bin/bash
echo "Checking for older files now..." >>/tmp/list
oIFS=$IFS; IFS=
tree_file=(`find /Datafolder/ -type f -ctime +1460 -exec echo '{}' +`)
IFS=$oIFS
tmplist=/tmp/list #world-writable=unsafe directory
for i in "${tree_file[@]}"
do
echo Files are "$i"
done >$tmplist
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.