How to Copy a File with '$' in Name in Linux

Unable to copy a file with '$' in name in Linux

The shell will interpret $Config as a variable. And it will expand to empty string.

You can put single quotes around to keep the literal value:

cp 'TopSample$Config.class' /home/praveen/com/config/

Another way is to escape the $(dollar sign) by using \(backslash)

cp TopSample\$Config.class /home/praveen/com/config/

How to copy files with the same name in different source dir and rename in destination dir?

If you don't need to put everything in the same path, you could maintain the structure using --parent :

$ cp --parent */abc.zip ~/dest

$ tree ~/dest
~/dest
├── 1
│   └── abc.zip
├── 2
│   └── abc.zip
└── 3
   └── abc.zip

Copy all files in folder to another folder prepending a . to the file name and rename it back to original file name

Let's suppose we have two directories as follows:

$ ls -a foo*
foo1:
. .. file1 file2 file3 'file 4'

foo2:
. ..

If we execute next command:

$ for file in foo1/* ; do base=$(basename "$file"); cp "foo1/$base" "foo2/.$base"; mv "foo2/.$base" "foo2/$base"; done

We will get at the end:

$ ls -a foo*
foo1:
. .. file1 file2 file3 'file 4'

foo2:
. .. file1 file2 file3 'file 4'

I think this is what you wanted.

Moreover, the file names with spaces inside will be correctly handled.

What characters are forbidden in Windows and Linux directory names?

A “comprehensive guide” of forbidden filename characters is not going to work on Windows because it reserves filenames as well as characters. Yes, characters like
* " ? and others are forbidden, but there are a infinite number of names composed only of valid characters that are forbidden. For example, spaces and dots are valid filename characters, but names composed only of those characters are forbidden.

Windows does not distinguish between upper-case and lower-case characters, so you cannot create a folder named A if one named a already exists. Worse, seemingly-allowed names like PRN and CON, and many others, are reserved and not allowed. Windows also has several length restrictions; a filename valid in one folder may become invalid if moved to another folder. The rules for
naming files and folders
are on the Microsoft docs.

You cannot, in general, use user-generated text to create Windows directory names. If you want to allow users to name anything they want, you have to create safe names like A, AB, A2 et al., store user-generated names and their path equivalents in an application data file, and perform path mapping in your application.

If you absolutely must allow user-generated folder names, the only way to tell if they are invalid is to catch exceptions and assume the name is invalid. Even that is fraught with peril, as the exceptions thrown for denied access, offline drives, and out of drive space overlap with those that can be thrown for invalid names. You are opening up one huge can of hurt.

Is it possible to use / in a filename?

The answer is that you can't, unless your filesystem has a bug. Here's why:

There is a system call for renaming your file defined in fs/namei.c called renameat:

SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname,
int, newdfd, const char __user *, newname)

When the system call gets invoked, it does a path lookup (do_path_lookup) on the name. Keep tracing this, and we get to link_path_walk which has this:

static int link_path_walk(const char *name, struct nameidata *nd)
{
struct path next;
int err;
unsigned int lookup_flags = nd->flags;

while (*name=='/')
name++;
if (!*name)
return 0;
...

This code applies to any file system. What's this mean? It means that if you try to pass a parameter with an actual '/' character as the name of the file using traditional means, it will not do what you want. There is no way to escape the character. If a filesystem "supports" this, it's because they either:

  • Use a unicode character or something that looks like a slash but isn't.
  • They have a bug.

Furthermore, if you did go in and edit the bytes to add a slash character into a file name, bad things would happen. That's because you could never refer to this file by name :( since anytime you did, Linux would assume you were referring to a nonexistent directory. Using the 'rm *' technique would not work either, since bash simply expands that to the filename. Even rm -rf wouldn't work, since a simple strace reveals how things go on under the hood (shortened):

$ ls testdir
myfile2 out
$ strace -vf rm -rf testdir
...
unlinkat(3, "myfile2", 0) = 0
unlinkat(3, "out", 0) = 0
fcntl(3, F_GETFD) = 0x1 (flags FD_CLOEXEC)
close(3) = 0
unlinkat(AT_FDCWD, "testdir", AT_REMOVEDIR) = 0
...

Notice that these calls to unlinkat would fail because they need to refer to the files by name.

Use a text file (containing file names) to copy files from current directory to new directory

To get only matching filenames from search.txt I would do this:

find . -type f -name '*.fasta' -print0 | grep -zf search.txt | xargs -r0 cp -t target-dir/

It will find all files with the extension .fasta, display only the ones with matching patterns in search.txt, and bulk cp them to target-dir, and each filename is terminated with a nullbyte in case filenames contain newlines.

a simple copy files based on names into two directory with bash

Given:

$ ls -1
part=2020-02-03
part=2020-03-02
part=2020-03-15
part=2020-05-01
part=2020-05-02
part=2020-05-03

The date part of your file names look like a form of ISO 8601 and therefore can be compared lexicographically (as strings).

Use a glob (rather than trying to parse ls), split the file name on the = and compare to the cutoff using string comparisons:

cut="2020-03-10"
for fn in part=*; do
if [[ "${fn#*=}" < "$cut" ]]; then
# ^ split the filename on '='
echo "$fn => dir 1"
# instead of echoing -- you would mv "$f" "new_path 1"
else
echo "$fn => dir 2"
# again -- replace with the mv you want
fi
done

This prints:

part=2020-02-03 => dir 1
part=2020-03-02 => dir 1
part=2020-03-15 => dir 2
part=2020-05-01 => dir 2
part=2020-05-02 => dir 2
part=2020-05-03 => dir 2

You should be able to take it from there!



Related Topics



Leave a reply



Submit