You aren't executing anything. When you put something in single quotes (`''`), that's just a string, so `'mv "$file" "$var1"'` is not a command, it's a string and doesn't do anything. A string by itself is just a true statement. In order to execute the command, you need to use: ``` system "mv", "--", $file, $var1; ``` (**Not** <strike>`system("mv '$file' '$var1'")`</strike> which would introduce a command injection vulnerability). But there's no need for that, `perl` has a `rename()` function, so you can do: ``` rename($file, $var1) ``` Next, you really shouldn't parse the output of `ls`, that is [a very bad idea and fragile][1]. It is also completely unnecessary in Perl (or any other programming language). If you want to match all files in the current directory containing the string `pre_` (which is what your `grep` does—you don't need the `grep`, by the way, you could have just used `ls -d -- *pre_*`), you can use `glob()` like this: ``` my @files = glob("*pre_*"); ``` So, putting all that together, this is what you were trying to do: ``` #!/usr/bin/perl -w use File::Glob qw(:globally :nocase); my @files = glob("*pre_*"); foreach $file ( @files ) { my @names = split(/pre_/i, $file); rename($file, $names[1]); } ``` But this isn't really a good idea. If you have two files with the same prefix (e.g. `pre_file1` and `apre_file1`), then the first file will be overwritten by the second file since, in this example, both files would be renamed to `file1` because your command would remove `pre_` and everything before it. So you can add a warning and skip those files: ```perl #!/usr/bin/perl -w use File::Glob qw(:globally :nocase); my @files = glob("*pre_*"); foreach $file ( @files ) { my @names = split(/pre_/i, $file); if (-e $names[1]) { warn "Warning: Not renaming '$file' to '$names[1]' " . "because '$names[1]' exists.\n"; next; } rename($file, $names[1]) or warn "rename '$file': $!\n"; } ``` ---- Of course, all of this is reinventing the wheel. You can just install `perl-rename` (on Debian, Ubuntu, etc. run `apt install rename`, on other systems it might be called `prename` or `perl-rename`), and then you can do (although this is not case insensitive, it only finds files containing `pre_`): ``` rename -n 's/.*?pre_//si' ./* ``` The `-n` causes `rename` to just print what it would do, without actually renaming. Once you are sure the renaming works as expected, run the command again without the `-n` to actually rename the files. Here the shell passes *all* (non-hidden) files to `rename` and `rename` will ignore the files whose name the `perl` code doesn't change. You could also tell the shell to only pass the file names that contain `pre_` case-insensitively with `./~(i)*pre_*` in `ksh93`, `./(#i)*pre_*` in `zsh -o extendedglob`, setting the `nocaseglob` option globally in `bash`, `zsh` or `yash` or use `./*[pP][rR][eE]_*`. [1]: https://mywiki.wooledge.org/ParsingLs