File Names with Spaces in Bash

Find files with spaces in the bash

Use find command with a space between two wildcards. It will match files with single or multiple spaces. "find ." will find all files in current folder and all the sub-folders. "-type f" will only look for files and not folders.

find . -type f -name "* *"

EDIT

To replace the spaces with underscores, try this

find . -type f -name "* *" | while read file; do mv "$file" ${file// /_}; done

How do I store file names that have spaces in a variable in shell script

If the filenames don't contain newlines

grep .txt MYFILES.txt | while IFS= read -r file ; do
echo "$file"
done

File names with spaces in BASH

First, you don't need ls. By using ls in backtics, you implicitly make bash parse a string into a list, which splits by whitespaces. Instead, make bash generate the list and separate it without such quirks:

Also, you need to enclose all $i usages into quotes, to make bash substitute it as a whole, not as a string split to separate words.

Here's the script that demonstrates both ideas:

for i in *.jpg ; do 
echo "$i";
done

How to make bash script take file names with spaces?

You need double quotes inside the backticks. The outer set isn't sufficient.

echo "first line is `head -1 "$file_name"`"

Also, do not put backslashes in the file name, since it's already quoted. Quotes or backslashes, but not both.

myfiles=("file with spaces.csv")
myfiles=(file\ with\ spaces.csv)

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:

  1. The variable contains one of the flags
  2. The variable contains the first piece of a parameter immediately after the flag
  3. 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]}]}"";

for name in `ls` and filenames with spaces

Just don't use command substitution: use for name in *.

Bash and filenames with spaces

Try this:

(IFS=$'\n'; grep -li 'regex' $(<listOfFiles.txt))

IFS is the Internal Field Separator. Setting it to $'\n' tells Bash to use the newline character to delimit filenames. Its default value is $' \t\n' and can be printed using cat -etv <<<"$IFS".

Enclosing the script in parenthesis starts a subshell so that only commands within the parenthesis are affected by the custom IFS value.



Related Topics



Leave a reply



Submit