How to add file to .gitignore with \n in the filename - linux

I just want to add file with file
name (file name contains \n) to .gitignore.
I try:
/file
name
/file\nname
file\
name
but have no luck.

Try
/file*name
* should match any characters.

Please tell me this is a homework assignment.
The .gitignore file uses a glob(7) style wildcard substitution so embedding a '*' should work. Linux really doesn't care about the filename spelling, so any character other than a '/' can go into a filename. On a command line be sure to use single-quotes (not double-quotes, mind you) so the shell doesn't get confused.
Reading the filenames from ls(1) and similar will split the name at the \n character because the glibc standard library is looking for newlines to find the end of a line of text. The '/' and '\n' characters are treated specially in many levels of the software stack, like the pathname of the file or splitting a buffer into lines or displaying the filename or letting awk(1), sed(1), and such scan a list of filenames.
But I agree with another poster: this is a bad idea. No, I take that back, it's a horrible idea. Long-term maintainability is going to be a nightmare.

Related

rename command for replacing text in filename from a certain point (character), but only up to, and maintaining the file extension

I've got a ton of files as follows
audiofile_drums_1-ktpcwybsh5c.wav
soundsample_drums_2-fghlkjy57sa.wav
noise_snippet_guitar_5-mxjtgqta3o1.wav
louder_flute_9-mdlsiqpfj6c.wav
I want to remove everything between and including the "-" and the .wav file extension, to be left with
audiofile_drums_1.wav
soundsample_drums_2.wav
noise_snippet_guitar_5.wav
louder_flute_9.wav
I've tried to do delete everything following and including the character "-" using
rename 's/-.*//' *
Which gives me
audiofile_drums_1
soundsample_drums_2
noise_snippet_guitar_5
louder_flute_9
And for lack of finding an easy way to rename all the files again, adding .wav the extension, I am hoping there is a slicker way to do this in one nifty command in one stage instead of 2.
Any suggestions?
Thanks
You can use rename 's/-[^\.]*\.wav$/\.wav/' *
The first part -[^\.]*\.wav$ searchs for a - followed by n chars that are not . followed by .wav and the end of filename. The end of filename and .wav is not strictly needed but it helps avoid renaming files you don't want to rename.
The /\.wav/ preserves the extension.
Please not that rename is not a standard utility, and is part of perl, so rename may not be available on every linux system.
This works in my specific case, but should work for any file extension.
rename -n 's/-.*(?=\.wav$)//' *
The command looks for all characters after and inclusive of the - symbol in the filename, then, using a positive lookahead** (?=\.wav$) to search for the characters (the file extension in this case) at the end of the filename (denoted by $, and replaces them with no characters (removing them).
** NOTE: A positive look ahead is a zero width assertion.
It will affect the match but it will not be included
in the replacement. (The '.wav' part will not be
erased)
In this example (?=\.wav$) is the positive lookahead. The dollar sign $, as in regex, denotes at the end of the line, so perfect for a file extension.

From each filepath in each line extract filename and add next to it

Given my text in a file:
/home/dir1/file1.txt
/home/dir2/file2.txt
...
/home/dirn/filek.txt
I would like it to be this text instead:
/home/dir1/file1.txt file1
/home/dir2/file2.txt file2
...
/home/dirn/filek.txt filek
Can I write this in vim?
This regex works:
:%s#.*/\(.*\)\.txt$#& \1#
The starting .*/ skips everything until the last slash (it's greedy, so it will catch all the directory part.)
Then we capture the filename in a group with \(.*\).
And finally we match the extension with \.txt and anchor it to the end of the line.
For the replacement, we use a & to keep the full path around and then add \1 to include the filename only.
We can use # as a delimiter, so we don't need to escape the /s. We only have one here, but that's an useful technique to use when paths are involved, so I'm making sure I use it here for consistency.
You might want to take a look at :help pattern-searches to learn more about Vim regexes you can use for search and substitutions.
(In general, the Vim documentation is great and the help system can be very useful if you know how to navigate it, see :help helphelp for more.)

Is there an alternative for the slash in a path?

I have an application which correctly escapes slashes ("/) in file names to avoid path traversal attacks.
The secret file has this path:
/tmp/secret.txt
I want to access this file by uploading a file with a special crafted file name (something like \/tmp\/secret.txt)
Is there any alternative syntax without the slashes which I can use so that Linux will read this file?
(I'm aware of URL encoding but as the escaping is done in the backend this has no use for me.)
No. The / is not allowed in a filename, no matter if it's escaped as \/ or not.
It is one out of only two characters that are not allowed in filenames, the other being \0.
This means that you obviously could use _tmp_secret.txt or -tmp-secret.txt, or replace the / in the path with any other character that you wish, to create a filename with a path "encoded into it". But in doing so, you can not encode pathnames that includes the chosen delimiter character in one or several of its path components and expect to decode it into the original pathname.
This is, by the way, how OpenBSD's ports system encodes filenames for patches to software. In (for example) /usr/ports/shells/fish/patches we find files with names like
patch-share_tools_create_manpage_completions_py
which comes from the pathname of a particular file in the fish shell source distribution (probably share/tools/create_manpage_completions.py). These pathnames are however never parsed, and the encoding is only there to create unique and somewhat intelligible filenames for the patches themselves. The real paths are included in the patch files.

Search ill encoded characters in a file on Linux

I have a lot of huge CSV files, some of them contain ill encoded characters: in vi, I see things like "<8f>" or "<8e>", for example.
First, I wanted to search and replace (:%s) all the characters, but it will be a very long process because I will have to do this everytime I have to handle a file, and I'm not always sure whether new characters are here.
Is it possible to detect such characters, so that I can extract lines containing ill encoded characters?
A simple command may exist, taking a file for argument and creating a file containing only the lines with a problem.
I don't know if I explain me very well...
Thanks in advance!
You could use :g/char/p [vim] to print all the lines in a given file, or the bash utility grep:
grep -lr 'char1\|char2\|char2' .
Will output all the files in a directory containing any of the chars you have listed (the -r makes it recursive and the -l lists only the filenames, rather than all the line matches.

How to rename a folder that contains smart quotes

I have a folder that was created automatically. The user unintentionally provided smart (curly) quotes as part of the name, and the process that sanitizes the inputs did not catch these. As a result, the folder name contains the smart quotes. For example:
this-is-my-folder’s-name-“Bob”
I'm now trying to rename/remove said folder on the command line, and none of the standard tricks for dealing with files/folders with special characters (enclosing in quotes, escaping the characters, trying to rename it by inode, etc.) are working. All result in:
mv: cannot move this-is-my-folder’s-name-“Bob” to this-is-my-folders-name-BOB: No such file or directory
Can anyone provide some advice as to how I can achieve this?
To get the name in a format you can copy-and-paste into your shell:
printf '%q\n' this*
...will print out the filename in a manner the shell will accept as valid input. This might look something like:
$'this-is-my-folder200\231s-name-200\234Bob200\235'
...which you can then use as an argument to mv:
mv $'this-is-my-folder200\231s-name-200\234Bob200\235' this-is-my-folders-name-BOB
Incidentally, if your operating system works the same way mine does (when running the test above), this would explain why using single-character globs such as ? for those characters didn't work: They're actually more than one byte long each!
You can use shell globbing token ? to match any single character, so matching the smart quotes using ? should do:
mv this-is-my-folder?s-name-?Bob? new_name
Here replacing the smart quotes with ? to match the file name.
There are several possibilities.
If an initial substring of the file name ending before the first quote is unique within the directory, then you can use filename completion to help you type an appropriate command. Type "mv" (without the quotes) and the unique initial substring, then press the TAB key to request filename completion. Bash will complete the filename with the correct characters, correctly escaped.
Use a graphical file browser. Then you can select the file to rename by clicking on it. (Details of how to proceed from there depend on the browser.) If you don't have a graphical terminal and can't get one, then you may be able to do the same with a text-mode browser such as Midnight Commander.
A simple glob built with the ? or * wildcard should be able to match the filename
Use a more complex glob to select the filename, and perhaps others with the same problem. Maybe something like *[^a-zA-Z0-9-]* would do. Use a pattern substitution to assign a new name. Something like this:
for f in *[^a-zA-Z0-9-]*; do
mv "$f" "${f//[^a-zA-Z0-9-]/}"
done
The substitution replaces all appearances of a characters that are not decimal digits, appercase or lowercase Latin letters, or hyphens with nothing (i.e. it strips them). Do take care before you use this, though, to make sure you're not going to make more changes than you intend to do.

Resources