wildcard in linux cp [closed] - linux

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
when I use * in cp, I think it follows the same rule as regex.
so "cp temp/* test/" should copies everything over, however, when temp folder is empty it throws exception saying it cannot find file or directory, which indicte * cannot match "nothing".
Then I create a file test.txt under temp and do:
cp temp/test.txt* test/
It works, which indicate * indeed match "nothing".
I get confused about the behavior. Can anyone explain a little bit?
Thanks

What's happening is the * expansion is done by your shell (bash probably). The pattern temp/testfile.txt* did match temp/testfile.txt (* matches zero or more characters), so bash passed that onto cp.
However, bash is set, by default, to pass the wildcard as-is on to the app if it doesn't match anything (there's an option called nullglob to turn this non-intuitive behavior off). So it passed temp/* literally to cp, which complained that it didn't exist.

The shell does the expansion, so it's not cp specific.
If not match is found, there's no substitution, the original string (temp/*) is reserved and passed to the application. Of course cp cannot find a file by that name.
# echo nosuchfile*
nosuchfile*
Some clarification for "nothing":
temp/* means entries (files/directories/...) in temp directory, but there weren't any files, so it failed.
temp/test.txt* means entries starting with test.txt in the temp directory.

Wildcard globbing is not the same as regular expressions, complete with their own rules.
Different shells have different rules ... you make want to look at Wikipdia to get an overview.

Related

Unix Renaming Files [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 5 years ago.
Improve this question
I want to rename files in a folder on UNIX using a script.
The format of the original file is:
abc.txt.temp
and I want to rename it to:
abc.txt
Many files use this format and I want to remove .temp from the original file name.
The answer Ciprian gave is certainly an option but I feel it's limiting.
The solution below is much more flexible as you don't have to actually count anything and you can remove text from any position rather than just the end.
The following command (1 line) will remove any mention of .temp in all the files:
for filename in *; do mv "$filename" "${filename//.temp/}"; done
Note The "*" means all files in current folder. You can use *.temp to achieve exactly the same result as Ciprian's method. (that is, only removing .temp from files ending with .temp)
I don't know about UNIX, but since the question also have the Linux tag it may just be a UNIX/Linux confusion.
Most GNU/Linux distributions have a rename command. Depending on the rename version, to replace foo with bar in files names the syntax may either be as simple as
rename foo bar files
or follow sed's regexp syntax :
rename 's/foo/bar/' files
In your case, you want to replace .temp with an empty string ('') in all files ending with .temp, so depending on your rename version one of these commands should work :
rename .temp '' *.temp
or
rename 's/\.temp$//' *.temp
Create the following script with a name like 'rename.sh':
#!/bin/bash
TARGET_DIR=$1
TARGET_FILES="$TARGET_DIR/*.temp"
for fileName in $TARGET_FILES
do
newFileName=${fileName::-5}
mv -v "${fileName}" "${newFileName}"
done
note The ${var:offset:length} expansion requires bash version 4 or higher.
Give it execution rights:
chmod a+x rename.sh
You need to call it and pass the name of the directory of the .temp files as a parameter. Call it like this:
./rename.sh /path/to/the/temp-files
The script loops over all the *.temp files in the target folder, extracts the last 5 chars from the file path ('.temp' is 5 chars) and moves the original file to the new file that doesn't contain .temp as the extension.
EDIT: tested on a CentOS 7

Linux symlink all files in directory is adding '*' [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 6 years ago.
Improve this question
I'm trying to symlink all files in a directory to a target directory, by doing:
ln -s /directory/* /target-directory
Problem is when I go into the target-directory, I'm seeing this '*', an asterisk in quotes, instead of all the files in the first directory. What am I doing wrong? Thanks.
Normally, what'd happen when you run ln -s /directory/* /target-directory is that the shell would expand /directory/* into a list of the (currently existing, visible) files in /directory/, and then pass that to ln in its argument list. The result would be equivalent to something like ln -s /directory/file1.txt /directory/file3.pdf /directory/file3.c /target-directory. Note that the ln command would not see the "*", and so would not include it in either the link source or target name.
Since "*" is being used as the link name, it's not getting expanded. There are a couple of reasons this might happen:
You might have the noglob shell option set. But you said in the comments that's not the case.
The shell expansion might not have matched any files, in which case the shell will simply pass it unchanged to ln, giving the result you describe. You said you created a file in the source directory, but did you re-test after doing that? Another possibility is that there's a typo in the directory path, so it's not finding a matching directory (let alone any files in it).
Oh, one more note: you said when you go to the target directory, you see an asterisk in quotes. Exactly how are you looking? Because if you're just using ls, it should not include quotes in the listing unless they're actually part of the filename. [Edit: Mark Plotnick pointed out that some versions of GNU ls do add quotes to some filenames.] I have no idea how the command you gave could add quotes to the filename.
Do not create the destination directory and do
ln -sd ./source ./destination
If you set the failglob option, you will get an error message if expansion of * is not possible.
shopt -s failglob

Adding any current directory './' to the search path in Linux [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 2 years ago.
Improve this question
How do you add any current directory './' to the search path for executables in Linux?
I know this is an old answer, but if anyone else stumbles across this question via Google like I did, here's a more detailed explanation.
If you want to make it so that search path contains the value of pwd at the time you set the search path, do:
export PATH=$PATH:$(pwd)
So, if pwd is /home/me/tmp, PATH will be set to $PATH:/home/me/tmp
However, If you want it so that whatever your present working directory is at the time you execute a command (ex; the value of pwd at any given time is in the search path), do:
export PATH=$PATH:.
So, if pwd is /home/me/tmp, PATH will be set to $PATH:.. If your present working directory contains a script called foo, then it would be fount in your PATH. If you change directories to one that does not contain foo, "foo" will not be found in the PATH any more.
You should note that having your present working directory in your PATH is a potential security risk, however.
If you want to permanently add the directory you're currently in to the PATH variable you can use
$ echo "export PATH=\$PATH:$(pwd)" >> ~/.bashrc
which will expand $(pwd) to the string literal of your current directory and append the quoted line to your bashrc which is loaded when you start your terminal. Note the \ in \$PATH is needed to escape the expansion of $PATH to its current value.
$ pwd
/path/to/suuuuuuuuuuuuuuuuuuuuper/long/foo/directory/bin
$ echo "export PATH=\$PATH:$(pwd)" >> ~/.bashrc
$ tail ~/.bashrc -n 1
export PATH=$PATH:/path/to/suuuuuuuuuuuuuuuuuuuuper/long/foo/directory/bin
For the current directory, you can just use a zero-length (null) directory name. You can use an initial or trailing colon, or a double colon. This is from the bash manpage, man bash:
PATH The search path for commands. It is a colon-separated list of
directories in which the shell looks for commands (see COMMAND EXECUTION
below). A zero-length (null) directory name in the value of PATH
indicates the current directory. A null directory name may appear as two
adjacent colons, or as an initial or trailing colon. The default path
is system-dependent, and is set by the administrator who installs bash.
A common value is
``/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin''.
Um...that didn't work for me. I would do
export PATH=$(pwd):$PATH
The command previously posted literally just adds the dot.
export PATH=$PATH:$PWD
works with bash 4.3.48
This is an old question, but I thought I'd add to it for those using the CSH or TCSH.
Adding the following to your .cshrc or .tcshrc will add the current directory to the environment path variable.
setenv PATH {$PATH}:.

rename multiple files shell in Linux [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
I have a number of files such as file_022.bmp, file_023.bmp...file_0680.bmp. I need to rename these to something a little bit more convenient such as file_1.bmp, file_2.bmp...file_658.bmp.
Is there a bash script that I could write to do this for me? Thanks for the help and advice.
Luke H
if you're on a debian based linux system then you can use the rename script which accepts regular expressions to rename files. Some more info because I find it hard to find the man page.
e.g.
harald#Midians_Gate:~$ ls p*.php
parse.php pd.php pgrep.php preg_based.php proc.php
suppose I want to change the extension to .perl and prepend the name with file_
then I use command:
rename -n 's/([a-z]*)\.php/file_$1.perl/' p*.php
would give
parse.php renamed as file_parse.perl
pd.php renamed as file_pd.perl
pgrep.php renamed as file_pgrep.perl
preg_based.php renamed as preg_file_based.perl
proc.php renamed as file_proc.perl
I select and capture the base filename ([a-z]*) and then use it in the substitution $1 and append .perl and prepend $1 with the regular string file_
the -n option makes it test run without changing anything
As you can see from this example your selecting regexp needs to be correctly thought out or you get cases like the above preg_based.php where you wanted file_preg_based.perl :)
to compensate for that I would've needed to use ([a-z_]*) here
It's one of the many reasons why I keep hanging on to debian, I'd love to find the equivalent for other non-debian systems though :-/
if you have files a.bmp,b.bmp,c.bmp
and you want to end up with file_1.bmp, file_2.bmp, file_3.bmp
using bash:
mkdir result
index=1
for i in *.bmp
do
mv "$i" "result/file_"$((index++)).bmp
done
notes:
using a subdirectory is advised to avoid accidentally overwriting a file that looks like file_xx.bmp
if you have too many files to fit in the command line after expansion you could use something like:
mkdir result
index=1
find . -name "*.bmp" | while read i
do
echo mv "$i" "result/file_"$((index++)).bmp
done
after inspecting the output remove the 'echo'

Shell tool to move in a complex directory structure [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 11 years ago.
Improve this question
My development machine is a linux host.
I have a complicated directory structure (like most of you, I assume), and I would like to move easily from one directory to the other, from within the shell. Specifically, welcomed features would be:
autocompletion (something like ido-mode in emacs)
regular expression directory / file matching
suggestion of recently visited directories (stack).
Possibilty to push/pop to the stack, get a listing of recently visited directories, ...
good integration of those features
console based
Do you know any tool which can satisfy those requirements?
In bash you can set CDPATH to a colon-separated directories that bash will search for when the argument to the cd does not exist.
$ man bash|grep -A3 '^\s\+CDPATH '
CDPATH The search path for the cd command. This is a colon-
separated list of directories in which the shell looks
for destination directories specified by the cd com‐
mand. A sample value is ".:~:/usr".
Once set, autocomplete will just work the way you'd expect it:
$ export CDPATH=dir1:dir2
$ cd somedir<tab>
Besides the current directory, bash will look into the directories in $CDPATH for the possible values.
Umm, any interactive shell(say, bash) already has nearly all of these features:
Press Tab once to auto-complete, and twice to show a list of possible completions.
find | grep reg.exp can be used for file matching, or find -exec grep reg.exp -H '{}' ';' to match contents
You can switch to the previous directory with cd -
pushd and popd can be used to push and pop directories

Resources