Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I'm having trouble using grep, the returned results are "n-empty", I mean without the 'n' character...

This is the script sample :

OLDIFS=$IFS
IFS="\\n"

i=$(grep -ril $1 *)

echo $i

IFS=$OLDIFS

I tried with IFS='\n' and IFS="\n" but the result displays the correct pathes only when I get rid of the IFS...

I'm using the result in a for theFile in $i; do......done loop, where the results are used in the right way and theFile is correctly displayed.

The only problem is that I have no correct console/file output of $i, which is a strategic data :

What I'm seeing in the console and the file which is written (sample) :

LecteurSy dicatio _sy dic/fiche_93.xml

What should be displayed and written (sample) :

LecteurSyndication_syndic/fiche_93.xml

Any idea ?

EDIT : complete script to play at home ;)

#!/bin/bash

monTerminal=$(tty) ; monTerminal=${monTerminal:9}
fichier="/home/importts/tmpCmdOpenFirst$monTerminal.xml"

PWD="`pwd`"
echo "== Recherche dans les fiches  ==" > "$fichier"

echo "Recherche : $1" >> "$fichier"
echo "Dans      : $PWD" >> "$fichier"

OLDIFS=$IFS
IFS="\\n"

i=$(grep -ril $1 *)

echo $i

echo "== Liste des fichiers trouves ==" >> "$fichier"

echo $i >> "$fichier"

IFS=$OLDIFS


#while read uneFiche
for uneFiche in $i;
do

echo "================================" >> "$fichier"
echo "== $uneFiche" >> "$fichier"
echo "================================" >> "$fichier"
echo "" >> "$fichier"

xmlindent "$uneFiche" >> "$fichier"

done < /home/robert/tmpCmdOpenFirst_liste.txt

nano "$fichier"
#rm $fichier
share|improve this question

migrated from serverfault.com Apr 27 '13 at 19:53

This question came from our site for professional system and network administrators.

3 Answers 3

up vote 1 down vote accepted

First, you've set IFS to \n, not to a newline. In bash, you can use $'…' to have backslash sequences interpreted as control characters:

IFS=$'\n'

Or you have the portable option of using a literal newline.

IFS='
'

The second problem is that IFS matters when you expand a variable. So it needs to be set when $i is expanded, it doesn't actually matter when you set i.

i=$(grep -ril -e "$1" -- *)
set -f; OLDIFS="$IFS"; IFS='
'
for uneFiche in $i; do
  set +f; IFS="$OLDIFS"
  …
done
set +f; IFS="$OLDIFS"

Additionally, don't forget to quote variables when you aren't splitting, e.g. the pattern you pass to grep. In case the pattern starts with -, pass it to grep with the -e option. Also put -- in front of the file names in case the first file name begins with -. Furthermore, in case a file name contains glob characters, turn off globbing with set -f before leaving a variable expansion unquoted.

A simpler approach would be to call grep on each file inside the loop. As an additional benefit, your script wouldn't break on file names containing newlines.

for uneFiche in *; do
  if grep -qri -e "$1" -- "$uneFiche"; then
    …
  fi
done
share|improve this answer
    
I don't understand why you are using set +f; IFS="$OLDIFS" in the loop : does it have any effect ? –  Benj Apr 29 '13 at 10:39
    
@Benj In case wildcard expansion or IFS is used in the loop (not the case here, but they could be if the code evolves). I also reset them after the loop in case the expansion happens to be empty. –  Gilles Apr 29 '13 at 11:12
    
I deported the edit I made in a separate answer, I think it is more readable. You can delete the edit I made to your answer, or let me know what is the more readable way. –  Benj Apr 30 '13 at 8:17

It is not easy to follow your problem description. The only useful information is missing, that is the output of grep -ril $1 * (or rather a sample of that) and an explanation what the problem is. I assume the problem is whitespace in some paths.

EDIT : There is the sample you requested :

The blanks are indeed 'n' chars...

1_LecteurSy dicatio _sy dic/fiche_174.xml
2_Tra sformatio XSL_tif/fiche_174.xml
3_CorrigerTIF_cor/fiche_174.xml
4_Tra sformatio XSL_ge /fiche_174.xml

/EDIT

IFS="\\n" is obviously wrong as you can easily check with echo "\\n". I am not even sure whether \n works in IFS definition. Use IFS=$'\n' instead or

IFS="
"

EDIT

The $'\n' form does not solve the problem. The "blank line" form makes things appear correctly, but the results are no more presented as a list (one per line). I keep the 'blank line' form since its result is roughly what I need.

/EDIT

Setting IFS does not make sense to me if you restore it before the for uneFiche in $i line. This way you just influence the line echo $i >> "$fichier" and that would have been a lot easier by quoting: i="$(grep -ril $1 *)", echo "$i" >> "$fichier"

EDIT

i="$(grep -ril $1 *)" seems not to have any effect.

/EDIT

If you have such problems with whitespace and word splitting then it might be easier to work with a pipeline like this:

grep -ril --null -- "$1" * | xargs -0 /my/script.sh

with /my/script.sh being

#!/bin/bash
fichier="/home/importts/tmpCmdOpenFirst$monTerminal.xml"

for uneFiche in "$@"; do
    echo "================================"
    echo "== $uneFiche"
    echo "================================"
    echo

xmlindent "$uneFiche"

done >> "$fichier"
share|improve this answer
    
Reply to @HaukeLaging Since your answer is quite consequent, I answered by editing it, step by step. –  Benj Apr 26 '13 at 14:43
    
@Benj No, no... I meant you should have started with the problem you were going to solve. Your initial problem hardly were the missing "n" which are a result of your trial to solve the former problem. So what about the output if you use the quotes as I showed you? –  Hauke Laging Apr 26 '13 at 14:51
    
The echo sample I put in the first Edit is the direct echo of $i. I very appreciate your help, thanks :). –  Benj Apr 26 '13 at 14:54
1  
@Benj Of course, quoting in one place does not change the result. It doesn't matter where the word splitting occurs. You have to quote both cases, i= and echo. –  Hauke Laging Apr 26 '13 at 14:58
    
Okay, I wasn't aware of that. –  Benj Apr 29 '13 at 10:36

There is the final script which works, thanks to Gilles :

#!/bin/bash

# use a buffer file per terminal, permits multiple users
monTerminal=$(tty) ; monTerminal=${monTerminal:9}
fichier="........./tmpCmdFiche$monTerminal.xml"

PWD="`pwd`"
echo "== Recherche dans les fiches  ==" > "$fichier"

echo "Recherche : $1" >> "$fichier"
echo "Dans      : $PWD" >> "$fichier"

i=$(grep -ril -e "$1" -- *)

set -f
OLDIFS="$IFS"
IFS='
'

echo "== Liste des fichiers trouves ==" >> "$fichier"

echo "$i" >> "$fichier"

for uneFiche in $i; do

set +f; IFS="$OLDIFS"

echo "================================" >> "$fichier"
echo "== $uneFiche" >> "$fichier"
echo "================================" >> "$fichier"
echo "" >> "$fichier"

xmlindent "$uneFiche" >> "$fichier"

done < ............/tmpCmdOpenFirst_liste.txt

set +f
IFS="$OLDIFS"

And then a sample of the cmdFiche somethingsosearch command result :

== Recherche dans les fiches  ==
Recherche : somethingsosearch
Dans      : ............/XMLs/.........
== Liste des fichiers trouves ==
1_ImportationZip_zip/file2.xml
2_ImportationSuppSyndication_syndic/file19.xml
3_ModifierOrdreImages_ordre/fiche_44.xml
4_CorrigerPeriodesViaSyndication_periodes/fiche_44.xml
5_TransformationXSL_tif/fiche_44.xml
6_CorrigerRaisonSocialeViaSyndic_raisonsociale/fiche_44.xml
7_ExclureImportNoeuds_avantv2/fiche_44.xml
================================
== 1_ImportationZip_zip/file2.xml
================================

<?xml version="1.0" encoding="utf-8"?>

<tif:OI xmlns:tif="http://www.tourinfrance.net/Tourinfrance3/" xmlns:xsi="http://www.w$

    <!--Granule DublinCore-->

    <tif:DublinCore>

Awesome !

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.