rename regex not working in cygwin - regex

I am using cygwin under windows 7.
In my directory there are files like
fort.100
fort.101
...
fort.1xx
I want to give them all an extension _v1.
When I try to achieve it using rename by
rename 's/$/_v1/' fort.*
the prompt exit with no errors and nothing happens.
I then tried
rename -e 's/$/_v1/' fort.*, an error pops up,
rename: unknown option -- e
I also tried with a different delimiter # instead of / with no luck.
Now, I thought it was due to the character _ in the expression (I am a newbie to regex), I tried escaping it by \_ with no luck either. Again a try without _, for example,
rename 's/$/v11/' fort.* - nothing happens again.
Although I achieved my goal by
for file in fort.*; do mv $file $file\_v1; done, I wonder why rename doesn't work.
What am I doing wrong here? Is it because I am on cygwin?

The manual of rename does not match your expectations.
I see no regex capability.
SYNOPSIS
rename [options] expression replacement file...
DESCRIPTION
rename will rename the specified files by replacing the first occur‐
rence of expression in their name by replacement.
OPTIONS
-v, --verbose
Give visual feedback which files where renamed, if any.
-V, --version
Display version information and exit.
-s, --symlink
Peform rename on symlink target
-h, --help
Display help text and exit.
EXAMPLES
Given the files foo1, ..., foo9, foo10, ..., foo278, the commands
rename foo foo0 foo?
rename foo foo0 foo??
will turn them into foo001, ..., foo009, foo010, ..., foo278. And
rename .htm .html *.htm
will fix the extension of your html files.
for what you want to reach the easy way is:
for i in fort*; do mv ${i} ${i}_v1 ; done

I have found a workaround.
I replaced the util-linux rename to perl rename a separate package.
This was provided from #subogero from GitHub.
All the usual rename expressions is working.

Related

Use sed/regex to rename a file - bash with macOS

I have a list of files that a date has been added to the end.
ex: Chorus Left Octave (consolidated) (2020_10_14 20_27_18 UTC). The files will end with .wav or .mp3
I want to leave the (consolidated) but take out the date. I have come up with the regex and tested with regexr.com. It does format the text correctly there.
The regex is: /(\([0-9]+(.*)(?=.wav|.mp3))+/g
Now, I am trying to actually rename the files. In my terminal I have cd'ed into the folder with the files. Based on other answers here I have tried:
rename -n '/(\([0-9]+(.*)(?=.wav|.mp3))+/g' *.wav|*.mp3 - using rename installed with homebrew
sed '/(\([0-9]+(.*))+/g' *.wav|*.mp3
for f in *.wav|*.mp3; do mv "$f" "${f/(\([0-9]+(.*)(?=.wav|.mp3))+/g}” done
The first two do not throw any errors, but do not do any renames (I know that the -n after rename just prints out the files that will be changed, it doesn't actually change the files)
The last one starts a bash session.
I'd rather use the rename or sed, seems simpler to me. But, what am I doing wrong?.
In plain bash:
#!/bin/bash
pat='([0-9][0-9][0-9][0-9]_[0-9][0-9]_[0-9][0-9] [0-9][0-9]_[0-9][0-9]_[0-9][0-9] UTC)'
for f in *.mp3 *.wav; do echo mv "$f" "${f/$pat}"; done
Remove the echo preceding the mv after making sure it will work as intended. You may also consider adding the -i option to the mv in order to avoid clobbering an existing file unintentionally.

Is there a way for changing text file names in a folder using C++

I am working with a bunch of txt files(thousands) on my project. Each txt file has 'csv' information on it. The problem is that each txt file has a random name and I cannot create a code for loading them in my project due to it. So, I want to rename them in a particular pattern to make easier the loading of the files in my work. I will use C++ for accomplish this task.
I put all the txt files in a folder but I cannot see a way of renaming them using C++. How can I do this? is there a way to do it? Can someone help me?
You can use std::filesystem::directory_iterator and std::filesystem::rename (c++17), as documented here.
Disclaimer
This answer validity is based on a comment where the author precised they were not bound to the C++ language (it may be worth editing the question, the C++ tag, and the OS). This solution may work for UNIX systems supporting bash, that is most Linux distributions and all releases of Apple's macOS prior to macOS Catalina (correct me if I'm wrong).
Bash command line
Using the following bash command should rename all the files in a folder with increasing numbers, that is:
toto.csv -> 1.csv
titi.csv -> 2.csv etc
It assumes the ordering is not important.
a=1; for i in *; do mv -n "$i" "$a.csv" ; let "a +=1"; done
To test it, you can prepare a test folder by opening a terminal and typing:
mkdir test
cd test
touch toto.csv titi.csv tata.csv
ls
Output:
tata.csv titi.csv toto.csv
Then you can run the following command:
a=1; for i in *; do mv -n "$i" "$a.csv" ; let "a +=1"; done
ls
Output:
1.csv 2.csv 3.csv
Explication:
a=1 declare a variable
for i in *; begin to iterate over all files in the folder
do mv will move (rename) a file of the list (that is, the variable $i) to a new name called a.csv
and we increment the counter a, and close the loop.
the option -n will make sure no file gets overwritten by the command mv
I assumed there was no specific criterion to rename the files. If there is a specific structure (pattern) in the renaming, the bash command can probably accommodate it, but the question should then give more details about these requirements :)

Change the name of many files

How can I rename many files. Remove the digits at the beginning.
I have a Mac. All the files are in the same folder.
The pattern is:
1, 2 or 3 digits - any name.php
With Regular Expression, I think it would be:
\d*-(.*).php
For example:
1-marketing.php
2-3D.php
3-without.php
I want to remove the numbers and the dash at the beginning.
In the example it would be:
marketing.php
3D.php
without.php
What I have explored two ways:
Select the files > ctrl click > rename items. This is a fantastic method to change the name of files. But I think it cannot be used in this case. If I understand, it does not support Regex. Am I right?
Terminal. I am not very familiar with terminal. I tried mv 1-marketing.php marketing.php It works for 1 file, but how can I do the same for many? I am new with the terminal. If it can be done, please explain the basic.
Open the terminal app in Mac OS X and navigate to the folder containing the .php files
cd /my/path/to-php-files/
and run the below command on the command-line.
for file in *.php; do mv -v "$file" "${file#*-}"; done
The bash parameter expansion syntax ${file#*-} removes the characters before - from the beginning, so ideally 3-number-without.php becomes number-without.php
(or) use the perl rename utility not available by default in Mac OS, you can download and install it with homebrew 🍺:
brew install rename
and do
rename -n 's/^(\d+)-(.*)/$2/' *.php
The -n is just for a dry-run to see how the files are to be renamed, remove it as
rename 's/^(\d+)-(.*)/$2/' *.php
for the actual renaming.

hg: how to exclude "*.xll" file but not xll directory

In my .hgignore file, I am trying to ignore all generated xll files. I (unfortunately) have a directory called "xll" within the domain of the repository, and I do not want to ignore the directory itself.
I have tried:
syntax: regex
\.xll$
which I thought should mean "match all that ends in '.xll'"
and
syntax: regex
*.\.xll$
which I thought should mean "match all that have at least one arbitrary character, followed by '.xll'".
With either of the above, the directory is not ignored (yay) but neither is a file foobar.xll (darn). If I use a bare "xll" with regex, or "*.xll" with glob, both the directory and the file are ignored.
This is in linux (Ubuntu 10.04.4) with hg 2.6 (TortoiseHG 2.8) (I'm observing the effect in Nautilus via the presence or absence of "X" icons).
Thanks in advance!
EDIT
(adding comments in here as they are too long to fit in a comment...)
Thanks for all the responses. Turns out I was misinterpreting some things. So:
- because I used "regex" instead of "regexp" (and I had "glob" at top of file), whatever I put on the line that referred to "xll" was being interpreted by "glob", so the line did have an effect (which made me think, incorrectly, that the "syntax: regex" line was doing what I thought it was
- by coincidence, all the files in my "xll" directory were filtered out (as they should have been) by other lines in .hgignore, and not by the "*.xll" line
- consequently, in Nautilus, the xll directory was marked as "ignored", not because the filter ignoring the entire directory, but instead because other filters were filtering all files within that directory
Bottom line, the *.xll I had under "syntax: glob" was actually filtering out files exactly as desired. The feedback in Nautilus was just different than I expected.
It's .*\.xll$, not *.\.xll$.
Using glob syntax works well for me:
syntax: glob
*.xll
When I create a directory named xll with an untracked file, I still see the file in the output from hg status:
$ mkdir xll
$ touch a.xll x.txt xll/b.xll xll/y.txt
$ echo 'syntax: glob\n*.xll' > .hgignore
$ hg status
? .hgignore
? x.txt
? xll/y.txt
Using \.xll$ with syntax: regexp also works great for me.

Copy and Rename Multiple Files with Regular Expressions in bash

I've got a file structure that looks like:
A/
2098765.1ext
2098765.2ext
2098765.3ext
2098765.4ext
12345.1ext
12345.2ext
12345.3ext
12345.4ext
B/
2056789.1ext
2056789.2ext
2056789.3ext
2056789.4ext
54321.1ext
54321.2ext
54321.3ext
54321.4ext
I need to rename all the files that begin with 20 to start with 10; i.e., I need to rename B/2022222.1ext to B/1022222.1ext
I've seen many of the other questions regarding renaming multiple files, but couldn't seem to make it work for my case. Just to see if I can figure out what I'm doing before I actually try to do the copy/renaming I've done:
for file in "*/20?????.*"; do
echo "{$file/20/10}";
done
but all I get is
{*/20?????.*/20/10}
Can someone show me how to do this?
You just have a little bit of incorrect syntax is all:
for file in */20?????.*; do mv $file ${file/20/10}; done
Remove quotes from the argument to in. Otherwise, the filename expansion does not occur.
The $ in the substitution should go before the bracket
Here is a solution which use the find command:
find . -name '20*' | while read oldname; do echo mv "$oldname" "${oldname/20/10}"; done
This command does not actually do your bidding, it only prints out what should be done. Review the output and if you are happy, remove the echo command and run it for real.
Just wanna add to Explosion Pill's answer.
On OS X though, you must say
mv "${file}" "${file_expression}"
Or the mv command does not recognize it.
Brace expansions like :
{*/20?????.*/20/10}
can't be surrounded by quotes.
Instead, try doing (with Perl rename) :
rename 's/^10/^20/' */*.ext
You can do this using the Perl tool rename from the shell prompt. (There are other tools with the same name which may or may not be able to do this, so be careful.)
If you want to do a dry run to make sure you don't clobber any files, add the -n switch to the command.
note
If you run the following command (linux)
$ file $(readlink -f $(type -p rename))
and you have a result like
.../rename: Perl script, ASCII text executable
then this seems to be the right tool =)
This seems to be the default rename command on Ubuntu.
To make it the default on Debian and derivative like Ubuntu :
sudo update-alternatives --set rename /path/to/rename
The glob behavior of * is suppressed in double quotes. Try:
for file in */20?????.*; do
echo "${file/20/10}";
done