problem wiht find command
Hi All,
I am using the below find command to find out all the directories and storing in an array. I want to handle the directory name with spaces also(LINUX FINAL) find /home/myadmin/ -maxdepth 1 -type d /home/myadmin/ /home/myadmin/LINUX FINAL /home/myadmin/Downloads I have modifies the above command as to handle the blank spaces in names find /home/myadmin/ -maxdepth 1 -type d -print0 But the output is here different /home/myadmin//home/myadmin/LINUX FINAL /home/myadmin/Downloads/ how do i print the output as before and also the blank spaces in directory names is also handled thanks in advance |
Quote:
Post your code, and we can try to help. |
Better try -exec option, as:
Code:
~$ find /home/myadmin/ -maxdepth 1 -type d -exec ls -la {} \; |
Find with spaces
Code:
find /home/myadmin/ -maxdepth 1 -type d -exec echo \"{}\" \; Code:
find /home/myadmin/ -maxdepth 1 -type d -print0 |xargs -0 command |
Please use ***[code][/code]*** tags around your code and data, to preserve the original formatting and to improve readability. Do not use quote tags, bolding, colors, "start/end" lines, or other creative techniques.
See here for how to safely process the output of a command and store it in an array: How can I read a file (data stream, variable) line-by-line (and/or field-by-field)? http://mywiki.wooledge.org/BashFAQ/001 How can I use array variables? http://mywiki.wooledge.org/BashFAQ/005/ How can I find and deal with file names containing newlines, spaces or both? http://mywiki.wooledge.org/BashFAQ/020 Note that the -print0 option separates each entry by an ascii null character. Since shell parameters cannot contain nulls, this makes them the safest delimiter to use in processing them. As non-printing characters, they won't show up visibly in the direct output of find, but they are there, and subsequent commands can use them to safely split the text. Code:
# This will load all regular files in a directory into an array: |
@David - Whilst the while loop makes perfect sense, is there a reason you know of why the following does not work?
Code:
IFS= read -r -d '' -a array <<<$(find -maxdepth 1 -type d -print0) |
Thanks a lot to all of you.
while the codes given by all of you were working fine but it seems those were not fitting to my requirement in my script. Here is what i want to do: find all the sub directories/ in a given directory and display their memory usage Code:
arr_dir=(`find "/home/myadmin" -maxdepth 1 -type d`) #storing the values in array /home/myadmin/LINUX FINAL /home/myadmin/Downloads though i am able to store the values in the array but when du comes to LINUX FINAL it assumes two diff values due to bad naming convention(space).Is possible to store values in the arry in sucha way that du also handles these kind of folders ? Please help..couldnt find a sol after tweaking my code in many ways |
I have also tried to take the input to array as the below codes:
@David and @whizje Code:
while IFS='' read -rd '' ; do |
Removing space character will change the directory name too, so it's not a good option. Instead you can leave the array and use process substitution, like:
Code:
while read -r dir; do |
Hi All,
I just found shell is adding a front slash automatically to LINUX FINAL after pressing tab key as shown below Code:
du -sh LINUX FINAL |
You can use double quote around file name, as:
Code:
du -sh \""$i"\" |
Quote:
Code:
while read -r dir; do Code:
done <<`find "/home/myadmin" -maxdepth 1 -type d -print` |
Awk is not necessory at all. You can use cut also. Also don't modify the original syntax. Following should work.
Code:
while read -r dir; do Also follow the post#5, and go through the links suggested by David. Most of your doubts will clear by following those links. |
Quote:
It does seem like it at first glance, doesn't it? But with read's -d delimiter set to null, it will only process up to the first null in the input text, and so there's nothing in the string for IFS to split on. The same thing would happen any time IFS and -d are set to the same thing. Incidentally, when I use the here string+command substitution as above I get the entire output as a single string, but when I use a process substitution for the input I get the first file only. It appears that the command substitution is acting as a parameter and silently dropping the nulls from the input. A bit of testing with cat -A bears this out. Code:
$ touch file{1..5} Code:
$ IFS='' read -ra array < <( find . -type f -print0 ) ; printf '%s\n' "${array[@]}" |
Quote:
1) $(..) is highly recommended over `..`. Please don't use backticks anymore unless you have to deal with a very old shell. 2) Once you have a string stored in a variable, instead of cut or other external commands, you can almost always use parameter substitution or another built-in string manipulation technique to process substrings from them. The fewer external processes you use, the faster your script will generally be, unless you are doing bulk modification of large blocks of text, in which case something like sed or awk may be faster. 3) Your here string syntax is wrong. It uses three arrows, not two. But actually, you really should be using a process substitution instead, at least when using bash. 4) I'd probably use printf instead of echo -e for the output. Code:
while IFS='' read -rd '' dir; do Although why you want to go to the trouble to extract the first column from the du output only to print it out again in exactly the same format (right down to the tab separating the columns) is beyond me. Speaking of which, instead of the above loop, you could just use find on its own: Code:
find "home/myadmin" -maxdepth 1 -type d -exec du -sh '{}' \; |
Quote:
So by escaping the quotes in the above command, you are in effect telling the shell (and subsequently du) that they are part of the filename itself. All you will get is a "file not found" error from the above. There are almost no cases where you can, or would want to, try to embed syntactical quotes like this. About the only time it would work at all is if some sort of double-parsing were being done, such as with eval. And double-parsing is something you generally want to avoid doing at all costs, for security reasons. I'm trying to put a command in a variable, but the complex cases always fail! http://mywiki.wooledge.org/BashFAQ/050 Eval command and security issues http://mywiki.wooledge.org/BashFAQ/048 |
Quote:
I have one doubt here-By doing this am i not making any changes to my IFS value ? The below code really ashamed me as i was going in a very complex way and i totally forgot about -exec which could do my job easily Code:
find "home/myadmin" -maxdepth 1 -type d -exec du -sh '{}' \; |
@David..
I would be thankful to you if you can please explain the below. i tried to dig but i didnt get any satisfactory explanation. i was of the view that -print0 option in find command allows file names that contain newlines or other types of white space to be correctly interpreted by programs that process the find output so i thpught du command which processes the ouput of find command in my script should be able to handle the file names with spaces (ex:LINUX FINAL). So why i need to use IFS again ? Code:
while IFS='' read -rd '' dir; do Code:
find "home/myadmin" -maxdepth 1 -type d -exec du -sh '{}' \; the IFS but couldn't relate to the above queries. |
Don't feel too embarrassed about doing it the hard way. We all experience that kind of thing sometimes. That's what helps you learn. Besides, I didn't really know myself whether you really intended your final output to be like that, or if you were just keeping it simple for this discussion. That's why I discussed the loop on detail first before mentioning it.
You don't need -print0 when using find alone because you aren't sending the output anywhere for another program to read. Instead you're executing du directly from within find, ignoring the shell entirely. The basic find syntax is this: Code:
find <starting dirs> <global options> <matching expressions> <actions> http://mywiki.wooledge.org/UsingFind http://www.grymoire.com/Unix/Find.html Re: your question about changing IFS, no you are not changing the global setting this way. Any simple command directly preceded by a variable setting (with only whitespace between them) will be launched with that variable in its environment, while not affecting the parent environment. Code:
IFS='' read -rd '' dir <input ( Edit: There's one final thing about IFS+read that I need to mention. When IFS includes whitespace, it will remove any of those whitespace characters found at the beginning or end of the string, even if there's no other word-splitting being done to the input (i.e. for setting a multiple variable list or array). Giving read an IFS set to null disables this so that you're guaranteed to get the entire input unaltered. ) As for your previous problems, when referring to post #7, the key issue is here: Code:
arr_dir=(`find "/home/myadmin" -maxdepth 1 -type d`) There is no easy way to work around this kind of situation. When expanding variables and command substitutions you can only have it treated as a single word (by quoting it), or have it word-split according to the IFS value. There's no way to tell it which spaces are inside the filenames and which are separating them. That's why you have to use null separators and a loop. Note that if the delimiter in the ouptput was a non-whitespace character, such as a colon, we could use IFS to split it safely in this fashion. But null separators don't work here, as I discovered in post #14. As for post #8, it's mostly ok actually, except for this: Code:
done < <(`find "/home/myadmin" -maxdepth 1 -type d -print0`) I'd also point out that this is a good example of why "$(..)" is better than backticks too. It would be easier to see the improper nesting. For a better understanding of IFS, start with the first three links to get a better understanding of how the shell processes arguments and whitespace internaly, and then the fourth one for more on how IFS works specifically. http://mywiki.wooledge.org/Arguments http://mywiki.wooledge.org/WordSplitting http://mywiki.wooledge.org/Quotes http://mywiki.wooledge.org/IFS Finally, having a good understanding of the shell's parsing order, what happens before or after what, will help you to avoid many mistakes like this. http://mywiki.wooledge.org/BashParser |
All times are GMT -5. The time now is 05:17 AM. |