Script to change first line of files in directory


 
Thread Tools Search this Thread
Top Forums Shell Programming and Scripting Script to change first line of files in directory
# 8  
Old 06-09-2012
Sorry, I didn't see these last two posts, I will give the code a try.

LMHmedchem

---------- Post updated at 03:01 PM ---------- Previous update was at 02:42 PM ----------

Well using the script posted by alister, I get the following error,

line 14: ed: command not found

line 14 is,

printf %s\\n 1c "$f" . w q | ed -s "$f"

If I add the code from agama, I get the following error,

line 5: cd: ./test_script/: No such file or directory
abort: could not switch to './test_script/' or parameter was missing

This is the code I am using,
Code:
#!/usr/bin/bash

# mol_filename2firstline_2.sh 

cd "$1"

if ! cd "${1:-no-such-directory}"     # also quote on the off chance that something in the path has spaces
then
   echo "abort: could not switch to '$1' or parameter was missing"
   exit 1
fi

for f in *; do
    [ ! -f "$f" ] && continue
    if [ -s "$f" ]; then
        printf %s\\n 1c "$f" . w q | ed -s "$f"
    else
        printf %s\\n "$f" > "$f"
    fi
done

run as,

./mol_filename2firstline_2.sh test_script/

I did stick my code into the loop to see what would happen, and it does work.
Code:
#!/usr/bin/bash
# mol_filename2firstline_3.sh 
# accepts a directly name dir/ and add replaces the first line of all .mol files
# with the filename

cd "$1"

for f in *.mol; do
   sed "1 c\\$f" $f > TEMP
   cp -f TEMP $f
   rm -f TEMP
done

It is rather slow at 1.4s for 20 files.

LMHmedchem
# 9  
Old 06-09-2012
Quote:
Originally Posted by LMHmedchem
Well using the script posted by alister, I get the following error,

line 14: ed: command not found
What operating system are you using that it doesn't have ed? I'm curious.

Quote:
Originally Posted by LMHmedchem
Code:
cd "$1"

if ! cd "${1:-no-such-directory}"     # also quote on the off chance that something in the path has spaces

You don't want to cd twice.

Regards,
Alister
# 10  
Old 06-09-2012
You only need the cd command in the if statement. Your directory is a relative path (doesn't start with a slant) and that is why it's erroring (there isn't a ./xxxx directory inside of the directory which you switched to earlier in the script.

You also are wasting effort copying the file back in your script (extra i/o adds to the latency).

Code:
#!/usr/bin/bash

# mol_filename2firstline_2.sh 
### unneeded cd "$1"

if ! cd "${1:-no-such-directory}"     # also quote on the off chance that something in the path has spaces
then
   echo "abort: could not switch to '$1' or parameter was missing"
   exit 1
fi

ls | while read f              # for *   doesn't handle filenames with spaces or large numbers of files. 
do
    [ ! -f "$f" ] && continue

    printf %s\\n "$f" >"$f.new"
    if ! sed '1d' "$f" >>"$f.new"
    then
        rm "$f.new"
    else
        mv "$f.new" "$f"
    fi
done

This User Gave Thanks to agama For This Post:
# 11  
Old 06-09-2012
Quote:
Originally Posted by alister
What operating system are you using that it doesn't have ed? I'm curious.
I'm running cygwin under windows xp. I know that cygwin has ed, but I may not have the package installed.

I didn't recognize that the cd command was going to execute twice.

Quote:
Originally Posted by agama
You also are wasting effort copying the file back in your script (extra i/o adds to the latency).
I ran you code on a set of 900 files and it takes ~45s, compared to 1m6s for my code, so this works pretty well.

The files I will use this on always have the extension .mol, I added that to my code for some extra security in case there happen to be some other files in the directory. Using your code, I could do ls *.mol | etc, but would that invoke the same issue you were trying to avoid by using ls in the first place (spaces, etc)? I suppose logic could be added to the loop to test if the filename ends in .mol and skip it if not.

Something like,
Code:
#!/usr/bin/bash

# mol_filename2firstline_4.sh 

if ! cd "${1:-no-such-directory}"     # also quote on the off chance that something in the path has spaces
then
   echo "abort: could not switch to '$1' or parameter was missing"
   exit 1
fi

ls | while read f              # for *   doesn't handle filenames with spaces or large numbers of files. 
do
    [ ! -f "$f" ] && continue

   EXTENSION=`echo ${f: -4}`

    if [ "$EXTENSION" == ".mol" ]; then
      printf %s\\n "$f" >"$f.new"
      if ! sed '1d' "$f" >>"$f.new"
      then
         rm "$f.new"
      else
         mv "$f.new" "$f"
      fi
   else
     echo $f # alert user if files other than .mol were found
   fi

done

LMHmedchem

Last edited by LMHmedchem; 06-09-2012 at 05:14 PM..
# 12  
Old 06-10-2012
You are correct, adding the globbing to the ls command would have the same possible consequences as using the glob on the for.

Your solution is on the right track; you don't need the echo to assign the value to EXTENSION, and since you are using bash, you don't even need to create the variable.

Code:
EXTENSION="${f: -4}"     # if you prefer to keep the variable, just assign it directly no need for backtics

Code:
ls | while read f              # for *   doesn't handle filenames with spaces or large numbers of files. 
do
    [ ! -f "$f" ] && continue

    if [[ "$f" == *".mol"  ]]; then
      printf %s\\n "$f" >"$f.new"
      if ! sed '1d' "$f" >>"$f.new"
      then
         rm "$f.new"
      else
         mv "$f.new" "$f"
      fi
   else
     echo $f # alert user if files other than .mol were found
   fi

Both bash and kshell support pattern matching (don't confuse with regular expression matching) inside of the [[...]] construct. This allows you to test for the contents of f without needing to chop it up.
# 13  
Old 06-10-2012
Quote:
Originally Posted by agama
Code:
if ! cd "${1:-no-such-directory}"     # also quote on the off chance that something in the path has spaces
then
   echo "abort: could not switch to '$1' or parameter was missing"
   exit 1
fi

ls | while read f              # for *   doesn't handle filenames with spaces or large numbers of files.

If you want to ensure that the script has been given a viable working directory, then $1 should be tested to confirm that it's non-empty and a directory. In that instance, blindly substituting a string in that way can be dangerous.

You are mistaken about the for f in * ... construct. Since pathname expansion occurs after field splitting, the expansion of * is absolutely safe with regard to IFS characters (by default, space, tab, and newline).

Ironically, the statement you replaced it with does not handle spaces correctly in all cases. If ls prints a filename with leading or trailing spaces, read will discard those, yielding either a non-existent file or a different file. Further, if the filename ended with a backslash, that backslash would be stripped and the next filename in the list, if any, would be appended. while IFS= read -r f fixes both issues.

Demonstration:
Code:
$ touch 'a1\' a2 '   spaces   '
$ # CORRECT RESULT
$ for f in *; do printf ':%s:\n' "$f"; done
:a1\:
:a2:
:   spaces   :
$ # ERRONEOUS HANDLING OF LEADING/TRAILING WHITESPACE AND TRAILING BACKSLASH
$ ls | while read f; do printf ':%s:\n' "$f"; done
:a1a2:
:spaces:
$ # FIX ONLY THE BACKSLASH
$ ls | while read -r f; do printf ':%s:\n' "$f"; done
:a1\:
:a2:
:spaces:
$ # FIX ONLY THE SPACES
$ ls | while IFS= read f; do printf ':%s:\n' "$f"; done
:a1a2:
:   spaces   :
$ # FIX BOTH
$ ls | while IFS= read -r f; do printf ':%s:\n' "$f"; done
:a1\:
:a2:
:   spaces   :

You are correct in that there may be a limit to how many files the pathname expansion in the for-loop list can handle, but if it's sufficient (usually is) for the task at hand, it's the simplest and safest method.

Regards,
Alister
This User Gave Thanks to alister For This Post:
# 14  
Old 06-10-2012
Quote:
Originally Posted by alister
You are mistaken about the for f in * ... construct. Since pathname expansion occurs after field splitting, the expansion of * is absolutely safe with regard to IFS characters (by default, space, tab, and newline).
I've always thought it was the other way round -- my twisted reasoning was that the shell had to expand the glob before it could split fields otherwise all files resulting from * would be treated as a single token.

Quote:
Originally Posted by alister
Ironically, the statement you replaced it with does not handle spaces correctly in all cases. If ls prints a filename with leading or trailing spaces, read will discard those, yielding either a non-existent file or a different file. Further, if the filename ended with a backslash, that backslash would be stripped and the next filename in the list, if any, would be appended. while IFS= read -r f fixes both issues.
Very embarrassing -- I wasn't even thinking along the lines of lead/trailing spaces.

Appreciate your pointing these out, and the samples. Fortunately, I'm always in learning mode Smilie
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

Change ? char from files and directory

Hello, I must change files and dirs name which contains che "?" char, I try this: rename 's/?/-/' *.* nothing, what's the problem? thanks (14 Replies)
Discussion started by: ionral
14 Replies

2. Shell Programming and Scripting

Apply 'awk' to all files in a directory or individual files from a command line

Hi All, I am using the awk command to replace ',' by '\t' (tabs) in a csv file. I would like to apply this to all .csv files in a directory and create .txt files with the tabs. How would I do this in a script? I have the following script called "csvtabs": awk 'BEGIN { FS... (4 Replies)
Discussion started by: ScKaSx
4 Replies

3. Shell Programming and Scripting

How to change a directory in shell script?

HI, I need to change the working directory by using the shell script /Export/home/user_name I have to go one step back like /Export/home Please help on this.:confused: (3 Replies)
Discussion started by: thelakbe
3 Replies

4. Shell Programming and Scripting

directory change in shell script

Hi, I am trying to change the directory in my script, & want to check if the directory is present or not . Ex: cd /home/xyz/temp/logs if the logs directory is not present i want to show the error in script instead of shell script error. Can anybody please help me on the same Thx in... (2 Replies)
Discussion started by: vls1210
2 Replies

5. Shell Programming and Scripting

Script to change file contents line by line

Hi, I'm struggling to write a script to do the following, -will go through each line in the file -in a specific character positions, changes the value to a new value -These character positions are fixed througout the file ----------------------- e.g.: file1.sh will have the following 3... (4 Replies)
Discussion started by: vini99
4 Replies

6. Linux

Change directory in a shell script

How do u change ur directory using a shell script?? (12 Replies)
Discussion started by: laxmi
12 Replies

7. Shell Programming and Scripting

change directory using shell script

How do u change ur directory using a shell script?? (0 Replies)
Discussion started by: laxmi
0 Replies

8. Shell Programming and Scripting

Change of directory thru script

:confused: Hi All, This script is not working. I want to change the directory as per users selection in current shell. Looks like it is spawning sub-shell internally. I have used . changedir.sh source changedir.sh ./changedire.sh But did not work. Currently shell directory remain the... (4 Replies)
Discussion started by: shiningram
4 Replies

9. Shell Programming and Scripting

Change Directory via a script?

I would like to have a script that would change my current working directory. However, any time I execute a 'cd' command in a script, it holds only for the life of that script -- the working directory on exit is the same as when the script was initiated. Is it possible to have the script return... (3 Replies)
Discussion started by: George Borrmann
3 Replies

10. UNIX for Dummies Questions & Answers

How do I change ownership of a directory and all of it's files.

How do I change ownership of a directory and all of it's files without changing permissions? (1 Reply)
Discussion started by: mborin
1 Replies
Login or Register to Ask a Question