1

I want to perform the following operations:

  • Find/replace (using regexp) all occurrences of <>:"\|? and replace it with an empty string
  • Find/replace (using regexp) all occurrences of ^\.+|\.+$ and replace it with an empty string

As a test, I manually created 2 folders (see screenshot) and ran these:

find "/home/users/Downloads/test" -regextype sed -regex "*<>:\|?*" -type d
find "/Users/chiyo/Downloads/test" -regextype sed -regex "*[<>:\|?]*" -type d
find "/Users/chiyo/Downloads/test" -regextype sed -regex "[<>:\|?]" -type d

and didn't find any.

I'm using this version of find.

=> find --version
find (GNU findutils) 4.6.0
Copyright (C) 2015 Free Software Foundation, Inc.

Any ideas how this can be done?

screenshot showing directories

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
mrjayviper
  • 2,051
  • @AndyDalton apologies for not providing example the first time. edited. – mrjayviper Jul 02 '18 at 14:57
  • "*<>:\|?*" looks closer to a shell glob than a regular expression - are you sure you understand the difference? – steeldriver Jul 02 '18 at 15:21
  • I don't see regextype of sed (mine is find (GNU findutils) 4.4.2) – ctrl-alt-delor Jul 02 '18 at 17:55
  • They are directories not folders (There is a good reason for this. an Item (file/directory) can be in more than one directory. In real life we can be in more than one directory, but not in more than one folder.) – ctrl-alt-delor Jul 02 '18 at 18:06
  • Do you have larry wall rename on you system? (Run which rename, follow the bread crumbs, the have a look in-side. If it starts #!/usr/bin/perl, then probably yes.) – ctrl-alt-delor Jul 04 '18 at 08:49
  • I see that you have not accepted an answer. Does one of the answers below, solve your problem? or do you need more help? – ctrl-alt-delor Dec 23 '18 at 22:56

2 Answers2

4

The first two examples are way out.

  • *<>:\|?* You can not start with a *. * means 0 or more of the previous atom. It also says < followed by > followed by : …, and ? is a special character.
  • *[<>:\|?]* This is closer you are using a character class, but still the * at the start.
  • [<>:\|?] This would match if it was a sub-regex match, but it is not. You need to match the entire filename, including directory path.

Therefore add regex codes to consume stuff before and after. ( . is any character, * is zero or more assurances of previous atom. Therefore .* will match anything.)

Therefore try .*[<>:\|?].*

You are not going to replace anything like this, and you have not told us what you want them replaced with.

3

Use -name rather than -regex (since it's the filenames you are actually interested in and -regex matches against the whole path):

find folder -type d -name '*[<>:\|?]*'

This would find any directory in or beneath folder whose name contains at least one of the characters <, >, :, \, | or ?.

To remove these characters from the directory names:

find folder -depth -type d -name '*[<>:\|?]*' \
    -execdir bash -c 'mv "$1" "${1//[<>:\|?]/}"' bash {} ';'

This assumes that the new name of a renamed directory is not already the name of an existing directory. Adding a test for name clashes:

find folder -depth -type d -name '*[<>:\|?]*' \
    -execdir bash -c '[ ! -e "${1//[<>:\|?]/}" ] && mv "$1" "${1//[<>:\|?]/}"' bash {} ';'

This would avoid trying to rename a directory if the new name already exists

The mv command is executed within a bash child shell. The shell is executed with the parent directory of the found directory as its working directory. It's using a bash-specific parameter substitution to delete all the offending characters from the filenames of the found directories.

The command also uses -depth to do a depth-first traversal of the directory structure under folder. Without this, find would try to enter directories that you just have renamed, and would fail.

Related:

Kusalananda
  • 333,661
  • Note -name uses globs, not regex. However some of the glob syntax is very similar to regex. I.e. character classes. – ctrl-alt-delor Jul 03 '18 at 07:31
  • @ctrl-alt-delor Except for when negating them, yes. In this specific case, there does not seem to be a need for regular expressions. – Kusalananda Jul 03 '18 at 07:32