6

I have tried various solutions mentioned in SO to solve this problem i am facing.

I want to find all files recursively and change certain text.

This is the command I am using in cygwin in windows

 find . -not -path \*.hg\* -exec sed -i 's/FCLP1025/FCLP1080/g' {} \;

The result i get is

sed: couldn't edit ./xxx/yyy/filename: not a regular file

Anything I am missing here?

3
  • 2
    Does it say "filename" or is it one of the names that is special to windows, like "CON"? You probably want a -type f in there anyhow so you don't try and edit directories.
    – icarus
    Commented Jul 17, 2019 at 6:04
  • It is actually a mix of filename and folders. But when I add "-type f", nothing happens. There is no output and the cursor is just waiting at the next line
    – T-Rex
    Commented Jul 17, 2019 at 6:13
  • What type of filesystem is this? Commented Jul 17, 2019 at 12:16

2 Answers 2

6

find is returning a list of all files and all directories. You should limit your search to try and find the files that actually contain the string. You could try adding:

find -type f ... #  Doesn't return directories
find -iname "*.txt" ... #  returns only files ending in '.txt' (case insensitive)

Or if you really want to get fancy, you could try only running sed on the files that actually contain the string by using grep:

grep -l -r 'FCLP1025' | xargs sed -i 's/FCLP1025/FCLP1080/g'

grep's -r searches recursively, and -l lists only the file names of the matching files. xargs then uses stdin an adds it as arguments to the following command, which is similar to the {} when using find -exec cmd {} \;.

Tested in bash on linux though, so if it doesn't work, you might want to see the grep --help in git-bash/cygwin if the flags are different. Usually they are the same though.

1
  • 1
    All of the core utils in Cygwin are built from GNU utils source code so its safe to assume there won't be any flag mismatches, fyi.
    – B Layer
    Commented Jul 18, 2019 at 1:46
1

Your command would potentially find directories (and other non-regular files). Directories are not regular files that you can edit with sed.

Adding the -type f test to the find command ensures that you only process regular files:

find . -type f -not -path \*.hg\* -exec sed -i 's/FCLP1025/FCLP1080/g' {} \;

or, with standard find options and more readable quoting,

find . -type f ! -path '*.hg*' -exec sed -i 's/FCLP1025/FCLP1080/g' {} \;

If you just want to skip any .hg directory completely, use -prune to delete them from the search path of find:

find . -name .hg -prune -type f -exec sed -i 's/FCLP1025/FCLP1080/g' {} \;

This makes find not even enter directories called .hg. Your command would enter such directories and test everything within them with -path, which would be slightly inefficient.

Note that there would be no output of your find command as sed -i (sed doing in-place editing) never produces output to the terminal (unless there are diagnostic messages). The output of sed -i goes into the files that it edits.

Also note that the last find command above would try to edit every file. If you know something about names of the files that you'd like to edit, you may want to add -name 'some pattern' just before the -exec to restrict the running of sed to only these files.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .