Removing binary symbol from text file - text

I'm using dos2unix command to convert a text file to unix format, but I'm getting this message for several files:
dos2unix: Binary symbol found at line 6115
dos2unix: Skipping binary file w1.txt
and when I open the text file in notepad++, I see the following:
How do I remove these binary symbols from the text file? Is there any command I could use?

These are private use only characters. More Info
If you are using dos2unix for removing carriage return char, you can try the below alternative.
sed -i -e 's/\r//g' file

Related

How to convert a CSV file to CSV UTF-8 (Comma Delimited) using a command in linux terminal?

I already have the spreadsheet saved inside the directory with the name 'status.csv' how can I see what type of csv and change it to CSV UTF-8 (Comma Delimited) using just the terminal?
If you need to convert the ; separators into commas, you can use sed (assuming the data does not contain any | symbol):
sed -i "s|;|,|g" status.csv
The flag -i means in place editing. You can remove it when testing.
If the data contains one or more pipe characters, you can use another separator for sed, as in the following command:
sed -i "s#;#,#g" status.csv
The command that is used most for checking a file type is file, but it just displays ASCII text for a .csv file AFAICS. I don't know any others.

How can I remove the BOM from a UTF-8 file? [duplicate]

This question already has answers here:
Remove file coding mark but preserve its coding
(2 answers)
Closed 1 year ago.
I have a file in UTF-8 encoding with BOM and want to remove the BOM. Are there any linux command-line tools to remove the BOM from the file?
$ file test.xml
test.xml: XML 1.0 document, UTF-8 Unicode (with BOM) text, with very long lines
Using VIM
Open file in VIM:
vi text.xml
Remove BOM encoding:
:set nobomb
Save and quit:
:wq
For a non-interactive solution, try the following command line:
vi -c ":set nobomb" -c ":wq" text.xml
That should remove the BOM, save the file and quit, all from the command line.
A BOM is Unicode codepoint U+FEFF; the UTF-8 encoding consists of the three hex values 0xEF, 0xBB, 0xBF.
With bash, you can create a UTF-8 BOM with the $'' special quoting form, which implements Unicode escapes: $'\uFEFF'. So with bash, a reliable way of removing a UTF-8 BOM from the beginning of a text file would be:
sed -i $'1s/^\uFEFF//' file.txt
This will leave the file unchanged if it does not start with a UTF-8 BOM, and otherwise remove the BOM.
If you are using some other shell, you might find that "$(printf '\ufeff')" produces the BOM character (that works with zsh as well as any shell without a printf builtin, provided that /usr/bin/printf is the Gnu version ), but if you want a Posix-compatible version you could use:
sed "$(printf '1s/^\357\273\277//')" file.txt
(The -i in-place edit flag is also a Gnu extension; this version writes the possibly-modified file to stdout.)
Well, just dealt with this today and my preferred way was dos2unix:
dos2unix will remove BOM and also take care of other idiosyncrasies from other SOs:
$ sudo apt install dos2unix
$ dos2unix test.xml
It's also possible to remove BOM only (-r, --remove-bom):
$ dos2unix -r test.xml
Note: tested with dos2unix 7.3.4
IF you are certain that a given file starts with a BOM, then it is possible to remove the BOM from a file with the tail command:
tail --bytes=+4 withBOM.txt > withoutBOM.txt
Joshua Pinter's answer works correctly on mac so I wrote a script that removes the BOM from all files in a given folder, see here.
It can be used like follows:
Remove BOM from all files in current directory: rmbom .
Print all files with a BOM in the current directory: rmbom . -a
Only remove BOM from all files in current directory with extension txt or cs: rmbom . -e txt -e cs
If you want to work on a bulk of files, by improving Reginaldo Santos's answers, there is a quick way:
find . -name "*.java" | grep java$ | xargs -n 1 dos2unix

How to print only txt files on linux terminal?

On my Linux directory I have 6 files. 5 files are txt files and 1 file a .tar.gz type file. How can I print to the terminal only the name of the txt files?
directory :dir
content:
ex1, ex2, ex3, ex4, ex5, ex6.tar.gz
Because you do not have a file extension (.txt) I would try to do it with exclusion.
ls | grep -v tar.gz
If you have multiple types then use extensions.
The command 'file', followed by the name of a file, will return the type of the file.
You can loop over the files in your directory, use each filename as input to the 'file' command, and if it is a text file, print that filename.
The following includes some extra output from the file command, which I'm not sure how to remove yet, but it does give you the filenames you want:
#!/bin/bash
for f in *
do
file $f | grep text
done
You can put this into a shell script in the directory you want to get the filenames from, and run it from the command line.
The suggestions of using the file command are correct. The problem here is parsing the output of this command, because (1) file names can contain pretty any character, and (2) the concrete output of the file command is a bit unpredictable, because it depends on how the so called magic files are present.
If we rely on the fact that the explanation text of the output of the file command - i.e. that part which explains what file it is - always contains the word text if it is a text file, and that it never contains a colon, we can process it as follows:
The last colon in the output must separated the filename from the explanation. Everything to the left is the filename, and if the word text (note the leading space before text!) occurs in the right part, we have a text file.
This still leaves us with those (hopefully rare) cases where a file name contains a non-printable character, they would be translated to their octal equivalent, which might or might not be what you want to see. You can suppress this by passing the -r option to the file command. This is useful if you want to process this filename further instead of just displaying it to the user, but it might corrupt your parsing logic, especially if the filename contains a newline.
Finally, don't forget that in any case, you see what the system considers a text file. This is not necessarily the same what you define to be a text file.
Updated Answer
As #hek2mgl points out in the comments, a more robust solution is to separate filenames using nul characters (which may not occur in filenames) and that will deal with filenames containing newlines, and colons:
file -0 * | awk -F'\0' '$2 ~ /text/{print $1}'
Original Answer
I would do this:
file * | awk -F: '$2~/text/{print $1}'
That runs file to see the type of each file and passes the names and types to awk separated by a colon. awk then looks for the word text in the second field and if it finds it, prints the first field - which is the filename.
Try running the following simpler command on its own to see how it works:
file *
Given this directory of files:
$ file *
1.txt: UTF-8 Unicode (with BOM) text, with CRLF line terminators
2.pdf: PDF document, version 1.5
3.pdf: PDF document, version 1.5
4.dat: data
5.txt: ASCII text
6.jpg: JPEG image data, JFIF standard 1.02, aspect ratio, density 100x100, segment length 16, baseline, precision 8, 2833x972, frames 3
7.html: HTML document text, UTF-8 Unicode text, with very long lines, with no line terminators
8.js: UTF-8 Unicode text
9.xml: XML 1.0 document text
A.pl: a /opt/local/bin/perl script text executable, ASCII text
B.Makefile: makefile script text, ASCII text
C.c: c program text, ASCII text
D.docx: Microsoft Word 2007+
You can see the only files that are pure ascii are 5.txt, 9.xml, and A-C. The rest are either binary or UTF according to file.
You can use a Bash glob to loop through files and use file to test each file. This save having to parse the output of file for the file names but relies on file to accurate identify what you consider to be 'text':
for fn in *; do
[ -f "$fn" ] || continue
fo=$(file "$fn")
[[ $fo =~ ^"$fn":.*text ]] || continue
echo "$fn"
done
If you cannot use file, which is certainly the easiest way, you can open the file and look for binary characters. Use Perl for that:
for fn in *; do
[ -f "$fn" ] || continue
head -c 2000 "$fn" | perl -lne '$tot+=length; $cnt+=s/[^[:ascii:]]//g; END{exit 1 if($cnt/$tot>0.03);}'
[ $? -eq 0 ] || continue
echo "$fn"
done
In this case, I am looking for a percentage of ascii vs non ascii in the first 2000 bytes of a file. YMMV but that allows finding a file that file would report as UTF (since it has a binary BOM) but most of the file is ascii.
For that directory, the two Bash scripts report (with my comments on each file):
1.txt # UTF file with a binary BOM but no UTF characters -- all ascii
4.dat # text based configuration file for a router. file does not report this
5.txt # Pure ascii file
7.html # html file
8.js # Javascript sourcecode
9.xml # xml file all text
A.pl # Perl file
B.Makefile # Unix make file
C.c # C source file
Since file does not consider the all ascii file 4.dat to be text, it is not reported by the first Bash script but is by the second. Otherwise -- same output.

Open a file using vim from the output of pipe command

I have a list of files in a text file abc.txt .
I have to read the nth line from the file and open the file using vim .
I have done this but the file at nth line doesn't open :-
sed -n 4p abc.txt | vim -
Trying to get 4th line from abc.txt and opening it using vim .But the output I get is content of file at that particular line number :-
The right command would be like this:
vim "$(sed -n 4p abc.txt)"
The difference is that this passes the output of sed as the first argument to vim. As a result, Vim will open that file.
In the command you've typed, the output of sed is piped to the standard input of vim. Since you're passing '-' as the argument to Vim, it assumes that the text to edit is what is coming through the standard input. This text is the filename, but not the contents of the file.
Yes I got it .
The command is
vim `sed -n 4p abc.txt`

Dealing with \r \n ^M ^# in text files using vim

When I save lines of data in excel files as tab delimited .txt files, and then open those files in VIM, I see that what was once a multi-line file in excel is now a single line file in VIM.
The "lines" can be separated in VIM using some substitution commands:
%s/^M/\r\n/g
After this, the "lines" are now separated by an ^#.
I deal with it using another substitution command:
%s/^#//g
My questions are:
Why do my multi-line txt excel files open as a single line in VI?
What is ^#?
Is there a better way to 'fix' my txt files?
You can often fix problems like this by running the following command:
dos2unix FILE_NAME
This will re-format the file's newline characters in place (ie it will modify your file).
(This command does not exist on Mac OS X)
If you don't have dos2unix (eg you're on a Mac), you can just use sed:
sed 's/^M$//' input.txt > output.txt
You can also use sed -i if you want to avoid creating a new file by performing the substitution in place.
You can enter ^M by typing CTRLV followed by CTRLM
More reading here
Try this command:
:%s/^M/\r/g
\r is the carriage return character vim uses. The ^M character is a newline character that is literally displayed.

Resources