0

I created a folder on my home directory call junk, and let's say I want to move all .cpp and .h files to it. How would I do it? My first thought is to start with find ~ -name *.cpp -print, but I don't know how to put in multiple patterns into the find argument, and I'm fairly lost after that.

asked Feb 8, 2014 at 11:16

3 Answers 3

2

portably:

cd &&
 find . -path ./junk -prune -o -type f \( \
 -name '*.h' -o -name '*.cpp' \) -exec sh -c '
 exec mv -i "$@" junk' sh {} +

Above excluding the junk folder itself from the search.

We're only removing regular files (-type f). There may be other types of files you want to move like symlinks, but beware that moving symlinks often break them.

The -i is a safeguard to avoid two files with the same name overriding each other.

answered Feb 8, 2014 at 11:30
5
  • please once check my updated answer, I think I have wrongly explain regex part Commented Feb 8, 2014 at 11:57
  • Could you please explain the extra calls to sh? As opposed to for instance find . ! -path './junk/*' -type f \( -name '*.h' -o '*.cpp' \) -exec mv -i "{}" ./junk/ \; Commented Feb 8, 2014 at 12:12
  • @grebneke, mv -i {} junk \; would run one mv per file. Using + means pass as may files as possible. You need sh to be able to have a junk argument after that list. With GNU or FreeBSD mv, you could have done -exec mv -it junk {} + instead. Commented Feb 8, 2014 at 12:43
  • @StephaneChazelas - I see, but there are two sh, what does the second one do sh {} +? Commented Feb 8, 2014 at 13:13
  • @grebneke, the first argument after sh -c code is for 0ドル (used for error messages...), "$@" starts after. Commented Feb 8, 2014 at 14:44
2

If on a GNU system, you can use the -regex option to find as shown below:

find . -regex ".*\.\(h\|cpp\)" -exec echo mv -v "{}" ~/junk \;

the output will show which command would be executed, like a dry run. If that looks good, you can remove the echo for applying.

Command Break Down

  • -regex : File name matches regular expression pattern, the default regex type it's uses emacs
  • ".*\.\(h\|cpp\)" : Since it's uses default regex type emacs, as per pattern match . (dot) means matches any character so to match exact . ( dot), we have to use escape character that is \. means for special character like (, | we have to use escape character. the pattern same as .*.(h|cpp) (regextype posix-egrep )
  • -exec : Execute command
  • { } : The string { } replaced by the matches file name
  • \; : Needs to be there as it tells the end of arguements provided to -exec variable

For more information on regular expression you can refer

answered Feb 8, 2014 at 11:27
2
  • can you break down what ".*\.(h\|cpp)" means? I'm a beginner so I'm completely lost. Commented Feb 8, 2014 at 11:33
  • @JonathanChiou See the updated answer.. Commented Feb 8, 2014 at 11:50
0

According to pinfo bash->Shell Expansions->Filename Expansion->3.5.8.1 Pattern Matching, the ‘extglob’ shell option may be enabled using the ‘shopt’ builtin. Apparently, Cargo, Rust's package manager and build tool also enables this in their bash completion script with shopt -s extglob. So my shell already recognizes several extended pattern matching operators. Lists of patterns can separated by a ‘|’.

‘?(PATTERN-LIST)’ Matches zero or one occurrence of the given patterns.

‘*(PATTERN-LIST)’ Matches zero or more occurrences of the given patterns.

‘+(PATTERN-LIST)’ Matches one or more occurrences of the given patterns.

‘@(PATTERN-LIST)’ Matches one of the given patterns.

‘!(PATTERN-LIST)’ Matches anything except one of the given patterns.

So we can do something like this.

mkdir -p ~/junk
for name in *.?(h|cpp); do echo mv -- "${name}" ~/junk/; done
mv -- ggml-alloc.h ~/junk/
mv -- ggml-backend.h ~/junk/
mv -- ggml-backend-impl.h ~/junk/
mv -- ggml-cuda.h ~/junk/
mv -- ggml.h ~/junk/
mv -- ggml-impl.h ~/junk/
mv -- ggml-metal.h ~/junk/
mv -- ggml-mpi.h ~/junk/
mv -- ggml-opencl.cpp ~/junk/
mv -- ggml-opencl.h ~/junk/
mv -- ggml-quants.h ~/junk/
mv -- llama.cpp ~/junk/
mv -- llama.h ~/junk/
mv -- unicode.h ~/junk/

And then remove the echo, if it purports to do what we want...

answered Jan 3, 2024 at 22:34
0

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.