The "read" command misinterprets file names containing spaces


 
Thread Tools Search this Thread
Top Forums Shell Programming and Scripting The "read" command misinterprets file names containing spaces
# 1  
Old 01-07-2012
The "read" command misinterprets file names containing spaces

The "read" command, which is built into bash, takes words from the standard input. However, "read" is not good at taking file names if the file names contain spaces. I would like my bash script to ask the user to enter file names, which may contain spaces. Can you think about any technique for this situation?

Suppose that the current directory has the following two files. Each file name contains a space.

Summer View.txt
Winter View.txt

Upon receiving these two file names, the "read" command misinterprets as if there were four files.

Code:
read -p "Enter files: "
for i in $REPLY ; do
  echo $i
done


-----

Summer\ View.txt Winter\ View.txt

When the above line was passed to "read",
the following output was returned.

Summer
View.txt
Winter
View.txt

-----

"Summer View.txt" "Winter View.txt"

When the above line was passed to "read",
the following output was returned.

"Summer
View.txt"
"Winter
View.txt"

I also tried single quotes, which ended up with the same erroneous output as double quotes.

-----

Is there any solution that will correctly interpret the above kinds of inputs as two files?

The delimiter can be changed from space to other characters by setting $IFS. However, I would rather stick on space for delimiter, because all characters including all symbols seem to be legal for file names or path names on modern GUI OS's.

If these file names are arguments to a script, then they would be correctly interpreted as two files. Consider the following script whose name is MyScript.

Code:
for arg ; do
  echo $arg
done


MyScript Summer\ View.txt Winter\ View.txt
and
MyScript "Summer View.txt" "Winter View.txt"

correctly output the following two file names.

Summer View.txt
Winter View.txt

However, I need user interaction. I want the user to pass file names in the middle of a script. Please show me a solution that correctly interprets file names when the user passes file names containing spaces upon the prompt by the script.

Thanks a lot, in advance.


Update:

To reflect the feedbacks from posts #2-#6, let me add the following.

I am not interested in any suggestions that attempt to change the delimiter or IFS, even if the change is temporary.

The real problem here is that the "read" command does not understand quotes and backslashes as the shell does. What the "read" command has obtained needs to be re-parsed by correctly handling quotes and backslashes like the shell. Can you think about any technique for such re-parsing?

Perhaps, is there any other command that reads the input from the user and that parses quotes and backslashes as the shell does?

Thanks a lot, in advance.

Last edited by LessNux; 01-07-2012 at 02:41 PM..
# 2  
Old 01-07-2012
Try this... Enter the file names separated by , (comma)

Code:
#!/bin/bash

read -p "Enter Files: " line

OLD_IFS=IFS
IFS=,

for i in $line
do
        echo $i
done

IFS=$OLD_IFS

Code:
 
ls -l
-rw-r--r-- 1 root root    7 2012-01-07 12:09 a b
-rw-r--r-- 1 root root    8 2012-01-07 12:11 c d

root@bt > ./run
Enter Files : a b,c d
a b
c d

HTH
--ahamed

Last edited by ahamed101; 01-07-2012 at 02:50 AM..
# 3  
Old 01-07-2012
Quote:
Originally Posted by ahamed101
Try this... Enter the file names separated by , (comma)


As I wrote in the original post, file names may contain any symbols including commas. So, changing the delimiter to comma by $IFS would create a new problem, and thus would not work.
# 4  
Old 01-07-2012
Quote:
Originally Posted by LessNux
As I wrote in the original post, file names may contain any symbols including commas.
I'm afraid you didn't wrote that. What would help is for you to tell what character is not going to be present in the file names. Otherwise, there would be no reliable way to parse the user's input.
Assuming your file names do not contain a new line, which is a reasonable expectation, this should work:
Code:
IFS="\n"
typeset -a a
read -p "Enter first file name (an empty string will end input): "
while true
do
  as=${#a[@]}
  [[ -z "$REPLY" ]] && break
  a[$as]="$REPLY"
  read -p "Enter next file name : "
done
for i in "${a[@]}" ; do
  echo "$i"
done

# 5  
Old 01-07-2012
Quote:
Originally Posted by LessNux
The delimiter can be changed from space to other characters by setting $IFS. However, I would rather stick on space for delimiter, because all characters including all symbols seem to be legal for file names or path names on modern GUI OS's.


Even a LF (\n, 0x0A) can be in file names on GUI OS's. Though it may be silly to put LF's in file names, it can accidentally happen when one copies from text and pastes it to a file name.

I thought about setting the delimiter to a non-printable character that is really unusual, such as ETX (0x03), ACK (0x06). However, it would be difficult for the user to input such non-printable characters at the read's prompt. I would like to let the user enter file names as he/she would enter on command line.

I discourage any attempts that resort to IFS.

The real problem is that the "read" command does not understand quotes and backslashes as the shell does. What the "read" command has obtained needs to be re-parsed by correctly handling quotes and backslashes like the shell. Can you think about any technique for such re-parsing?
# 6  
Old 01-07-2012
Isolate and scrub your proc's $@ variable. If there's a good chance that someone might paste in a bum set of chars, you'd want to exclude the chance of it break your flow.

If you'd assign the inbound $@ to its own variable (such as my_var="${@}"), you can then scrub this new variable for bad chars before you'd try to parse it further.
# 7  
Old 01-09-2012
Use bash to read the into an array:
Code:
read -p "Enter files: " -a vals
 
for((i=0; i < ${#vals[@]}; i++)) do
  echo "$i: ${vals[i]}"
done

On entry, escape spaces with backslash:
Code:
$ ./getfiles.sh
Enter files: Summer\ View.txt Winter\ View.txt
0: Summer View.txt
1: Winter View.txt


Last edited by Chubler_XL; 01-09-2012 at 01:10 AM..
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

Bash script - Print an ascii file using specific font "Latin Modern Mono 12" "regular" "9"

Hello. System : opensuse leap 42.3 I have a bash script that build a text file. I would like the last command doing : print_cmd -o page-left=43 -o page-right=22 -o page-top=28 -o page-bottom=43 -o font=LatinModernMono12:regular:9 some_file.txt where : print_cmd ::= some printing... (1 Reply)
Discussion started by: jcdole
1 Replies

2. UNIX for Dummies Questions & Answers

Using "mailx" command to read "to" and "cc" email addreses from input file

How to use "mailx" command to do e-mail reading the input file containing email address, where column 1 has name and column 2 containing “To” e-mail address and column 3 contains “cc” e-mail address to include with same email. Sample input file, email.txt Below is an sample code where... (2 Replies)
Discussion started by: asjaiswal
2 Replies

3. UNIX for Dummies Questions & Answers

Unix "look" Command "File too large" Error Message

I am trying to find lines in a text file larger than 3 Gb that start with a given string. My command looks like this: $ look "string" "/home/patrick/filename.txt" However, this gives me the following message: "look: /home/patrick/filename.txt: File too large" So, I have two... (14 Replies)
Discussion started by: shishong
14 Replies

4. Shell Programming and Scripting

awk command to replace ";" with "|" and ""|" at diferent places in line of file

Hi, I have line in input file as below: 3G_CENTRAL;INDONESIA_(M)_TELKOMSEL;SPECIAL_WORLD_GRP_7_FA_2_TELKOMSEL My expected output for line in the file must be : "1-Radon1-cMOC_deg"|"LDIndex"|"3G_CENTRAL|INDONESIA_(M)_TELKOMSEL"|LAST|"SPECIAL_WORLD_GRP_7_FA_2_TELKOMSEL" Can someone... (7 Replies)
Discussion started by: shis100
7 Replies

5. Shell Programming and Scripting

Compare file names and select correct elements to include in "for each loop"

Hi everyone, I`ll try to be most clear I can explaining my help request. I have 2 folders Folder A-->This folder receives files through FTP constantly Folder B-->The files from Folder A are unzipped and then processed in Folder B Sometimes Folder A doesn`t contain all... (2 Replies)
Discussion started by: cgkmal
2 Replies

6. Shell Programming and Scripting

"read" command ignoring leading spaces

I have to read a file line by line, change it and then update the file. Problem is, when i read the file, "read" command ignores leading spaces. The file is a script which is indented in many places for clarity. How to i make "read" command read leading spaces as well. (3 Replies)
Discussion started by: vickylife
3 Replies

7. Shell Programming and Scripting

read -p "prompt text" foo say "read: bad option(s)" in Bourne-Shell

Hallo, i need a Prompting read in my script: read -p "Enter your command: " command But i always get this Error: -p: is not an identifier When I run these in c-shell i get this error /usr/bin/read: read: bad option(s) How can I use a Prompt in the read command? (9 Replies)
Discussion started by: wiseguy
9 Replies

8. Shell Programming and Scripting

script to read a line with spaces bet " " and write to a file

Hi, I need a command in UNIX KSH below is the description... MAPPING DESCRIPTION ="Test Mapping for the calid inputs" ISVALID ="YES" NAME ="m_test_xml" OBJECTVERSION ="1" VERSIONNUMBER ="1" unix ksh command to read the DESCRIPTION and write to a file Test Mapping for the calid inputs... (3 Replies)
Discussion started by: perlamohan
3 Replies

9. Shell Programming and Scripting

How to remove "New line characters" and "spaces" at a time

Dear friends, following is the output of a script from which I want to remove spaces and new-line characters. Example:- Line1 abcdefghijklmnopqrstuvwxyz Line2 mnopqrstuvwxyzabcdefghijkl Line3 opqrstuvwxyzabcdefdefg Here in above example, at every starting line there is a “tab” &... (4 Replies)
Discussion started by: anushree.a
4 Replies

10. Shell Programming and Scripting

passing a list of dynamic names to a "PS" command in shell script?

Hi, I am new to shell script. This is my first post .I have written a small script which returns list of names starts with "ram" in /etc/passwd .Here is that:- #!/bin/ksh NAME_LIST="name_list.txt" cat /dev/null > $NAME_LIST evalcmd="cat /etc/passwd | grep "^ram?*" | cut -d: -f1" eval... (3 Replies)
Discussion started by: sachin.tendulka
3 Replies
Login or Register to Ask a Question