Shell script issue with filenames containing spaces
you're actually adding redundant "'" (which your echo invocation shows)
try this:
#!/bin/sh
for f in *
do
ls "$f"
done
Shell script issue with directory and filenames containing spaces
Use find -print0 | xargs -0
to reliably handle file names with special characters in them, including spaces and newlines.
find /bishare/IRP_PROJECT/SFTP/ -type f -print0 |
xargs -0 ls -al > "$Temp_Path/File_Posted_$CURRENT_DATE.txt"
Alternatively, you can use find -exec
which runs the command of your choice on every file found.
find /bishare/IRP_PROJECT/SFTP/ -type f -exec ls -al {} + \
> "$Temp_Path/File_Posted_$CURRENT_DATE.txt"
In the specific case of ls -l
you could take this one step further and use the -ls
action.
find /bishare/IRP_PROJECT/SFTP/ -type f -ls > "$Temp_Path/File_Posted_$CURRENT_DATE.txt"
You should also get in the habit of quoting all variable expansions like you mentioned in your post.
Shell script issue with filenames containing spaces while reading into an array
You're running the same command three separate times! And, the find
command can take a long time to run.
I would take a look at your loop and see if you can do all of your steps in that single loop:
file_count=0
find . -type f -print0 | while read -d $'\0' file
do
((file_count+=1)) #Count the number of files processed
here be dragons...
echo "The '$file' file contains '$word' $word_count times"
done
The -print0
argument separates out the file names with the NUL character (One of the two characters that can't be contained in a file name. For extra credit, can you name the other?) You pipe this into a while read file
to read the file name. The -d$'\0'
tells the read
to break up the words on the null character.
Not only does this take care of spaces in file names, but also tabs, double spaces, character returns, new lines, and almost anything else that can be tossed into the mix. You're guaranteed that you are reading one and only one file name no matter how funky that file name is.
Piping output of a command into a while read
statement is a fairly efficient operation. It can go in parallel. That is, while the output of the command is being piped, the while
loop is executing. Take a good look at this structure of this loop because you will be seeing it over and over again in your shell scripts.
The ((...))
is a mathematical operation.
The here be dragons... is where you fill in the logic to get the information you need. After all, it is a homework assignment. However, it looks like you have a good handle on shell scripting.
If you have to have these two arrays, I would pipe the output of the find
into an array, then use that array to put your information into the numarray
and filearray
. It's not efficient, but at least you aren't running the find
command three separate times.
Linux Scripting with Spaces in Filenames
So after reading through the commentary, we decided that although it may not be the right answer for every scenario, the right answer for this specific scenario was to extract the pieces manually.
Because we are building this for a pre-built script passing to it, and we aren't updating that script any time soon, we can accept with certainty that this script will always receive a -i, -o, and -e flag, and there will be spaces between them, which causes all the pieces passed in to be stored in different variables in $*
.
And we can assume that the text after a flag is the response to the flag, until another flag is referenced. This leaves us 3 scenarios:
- The variable contains one of the flags
- The variable contains the first piece of a parameter immediately after the flag
- The variable contains part 2+ of a parameter, and the space in the name was interpreted as a split, and needs to be reinserted.
One of the other issues I kept running into was trying to get string literals to equate to variables in my IF statements. To resolve that issue, I pre-stored all relevant data in array variables, so I could test $variable == $otherVariable.
Although I don't expect it to change, we also handled what to do if the three flags appear in a different order than we anticipate (Our assumption was that they list as i,o,e... but we can't see excatly what is passed). The parameters are dumped into an array in the order they were read in, and a parallel array tracks whether the items in slots 0,1,2 relate to i,o,e.
The final result still has one flaw: if there is more than one consecutive space in the filename, the whitespace is trimmed before processing, and I can only account for one space. But saying as we processed over 4000 files before encountering one with a space, I find it unlikely with the naming conventions that we would encounter something with more than one space.
At that point, we would have to be stepping in for a rare intervention anyways.
Final code change is as follows:
#!/bin/bash
IFS='|'
position=-1
ioeArray=("" "" "")
previous=""
flagArr=("-i" "-o" "-e" " ")
ioePattern=(0 1 2)
#echo "for loop:"
for i in $*; do
#printf "%s\n" "$i"
if [ "$i" == "${flagArr[0]}" ] || [ "$i" == "${flagArr[1]}" ] || [ "$i" == "${flagArr[2]}" ]; then
((position += 1));
previous=$i;
case "$i" in
"${flagArr[0]}")
ioePattern[$position]=0
;;
"${flagArr[1]}")
ioePattern[$position]=1
;;
"${flagArr[2]}")
ioePattern[$position]=2
;;
esac
continue;
fi
if [[ $previous == "-"* ]]; then
ioeArray[$position]=${ioeArray[$position]}$i;
else
ioeArray[$position]=${ioeArray[$position]}" "$i;
fi
previous=$i;
done
echo "extracting (${ioeArray[${ioePattern[0]}]}) to (${ioeArray[${ioePattern[1]}]}) with (${ioeArray[${ioePattern[2]}]}) encoding."
inputfile=""${ioeArray[${ioePattern[0]}]}"";
outputfile=""${ioeArray[${ioePattern[1]}]}"";
encoding=""${ioeArray[${ioePattern[2]}]}"";
deal with filename with space in shell
You shouldn't use ls
in for
loop.
$ ls directory
file.txt 'file with more spaces.txt' 'file with spaces.txt'
Using ls
:
$ for file in `ls ./directory`; do echo "$file"; done
file.txt
file
with
more
spaces.txt
file
with
spaces.txt
Using file globbing:
$ for file in ./directory/*; do echo "$file"; done
./directory/file.txt
./directory/file with more spaces.txt
./directory/file with spaces.txt
So:
for file in "$rule"/*.gz; do
echo "$file"
#tar -xf *.gz
#mv a b.xml to ab.xml
done
Whitespace in filenames in shell script
Don’t make it more complicated than it is.
cat "$FILE"
That’s all you need. Note the quotes around the variable. They prevent the variable from being expanded and split at whitespace. You should always write your shell programs like that. Always put quotes around all your variables, unless you really want the shell to expand them.
for i in $pattern; do
That would be ok.
How to pass a file name containing spaces as an argument to a command-line program?
You should be able to quote the filename (eg. "file name"), or use an escape sequence (eg. file\< space >name).
Related Topics
Changing the Owner of an Existing Process in Linux
Ada Program Works in Linux But Not in Gps Windows 10
/Var/Log/Daemon.Log Taking More Space How to Reduce It
Why Fftw on Windows Is Faster Than on Linux
Qserialport Cannot Open Tty After Application Has Previously Been Run by 'Root'
How to Modify Eip's Tracee Forked Procee
How to Share a Register Between Threads
Segmentation-Fault Error Happening with Assembly Code Program
Linux Ipc: Shared Memory Recovery
Bash/Linux Sort by 3Rd Column Using Custom Field Seperator
How Can a Program Detect If It Is Running as a Systemd Daemon
Gatttool Non-Interactive Mode --Char-Write
"Echo" Output Different Answer by Sh and Bash
How to Identify the User Who Owns a Process from /Proc/Pid
How to Set a Non-Standard Baudrate on a Serial Port Device on Linux